Add files via upload

This commit is contained in:
公明
2026-07-10 21:35:49 +08:00
committed by GitHub
parent 0251230654
commit c33e5f2026
9 changed files with 1032 additions and 43 deletions
+1
View File
@@ -8,6 +8,7 @@
- [Contributing Guide](contributing-guide.md): checklists for APIs, config, tools, frontend, DB, high-risk features, and docs.
- [Configuration Reference](configuration.md): `config.yaml` fields, hot-apply boundaries, recommended values, and source anchors.
- [Security Model](security-model.md): trust boundaries, HITL, tool execution, C2/WebShell, and data safety.
- [RBAC Administration](rbac.md): platform users, system/custom roles, permission catalog, per-permission scopes, resource assignments, Agent/MCP/robot boundaries, and API examples.
- [Architecture](architecture.md): request flow, module relationships, complexity hotspots, and design trade-offs.
- [API Reference](api-reference.md): authentication, OpenAPI, SSE, stability tiers, and common endpoints.
- [Troubleshooting](troubleshooting.md): diagnostic order, minimal commands, common misdiagnoses, and issue template.
+374
View File
@@ -0,0 +1,374 @@
# CyberStrikeAI RBAC Administration Guide
[中文](../zh-CN/rbac.md)
CyberStrikeAI can execute Agents, MCP tools, WebShell operations, C2 actions, and batch jobs. RBAC therefore applies beyond navigation visibility: it is enforced across HTTP APIs, resource queries, Agent contexts, built-in and external MCP tools, background jobs, and chatbot execution.
---
## 1. Two different kinds of roles
| Concept | Management location | Purpose |
|---------|---------------------|---------|
| **Platform role (RBAC Role)** | **Platform permissions** | Controls which features and resources a user may access |
| **AI testing role (Agent Role)** | **Roles** / `roles/*.yaml` | Controls Agent prompts, methodology, and candidate tools |
An AI testing role is not an authorization boundary. Selecting a penetration-testing role does not grant platform permissions, and granting RBAC permissions does not change the Agent prompt.
---
## 2. Authorization model
An operation is allowed only when all relevant checks pass:
```text
enabled account
+ required permission for the route/tool
+ scope attached to that permission
+ resource owner / explicit assignment / parent inheritance
+ additional rules for process-global operations
```
Request flow:
1. Login issues a Bearer token whose session contains user, roles, permissions, and per-permission scopes.
2. HTTP middleware maps the route to a permission, for example `GET /api/projects``project:read`.
3. Resource-ID requests also check ownership, explicit assignments, or supported parent inheritance.
4. Agent execution receives an immutable Principal through `context.Context`.
5. Built-in MCP tools authorize both the tool and resource IDs in tool arguments. External MCP has separate restrictions.
6. Denials are written to RBAC/audit logs.
Frontend button hiding is only a usability feature. The server is the security boundary.
---
## 3. Built-in platform roles
| Role | Scope | Default capability |
|------|-------|--------------------|
| **Administrator `admin`** | `all` | Every known permission, including RBAC, configuration, terminal, audit deletion, and global definition management |
| **Operator `operator`** | `assigned` | Normal read/write/execute work; excludes RBAC, core configuration, terminal, audit management, external MCP execution, and several global definition writes |
| **Auditor `auditor`** | `all` | Read permissions across modules plus `audit:read`; no writes |
| **Viewer `viewer`** | `assigned` | Read-only access within authorized resources |
System roles cannot be edited or deleted. Their grants are rebuilt from the current permission catalog during upgrade, preventing stale grants from older versions. Create custom roles for different job functions.
An account without a role can still authenticate but has almost no business capability; do not treat “no role” as a complete job profile.
---
## 4. Permission catalog
Permissions use `module:action`. Common actions are `read`, `write`, `delete`, and `execute`. The authoritative catalog for the running build is available in Platform permissions or `GET /api/rbac/metadata`.
| Module | Permissions |
|--------|-------------|
| Account | `auth:self` |
| Dashboard | `dashboard:read` |
| Chat | `chat:read`, `chat:write`, `chat:delete` |
| Agent | `agent:execute`, `agent:local-execute` |
| HITL | `hitl:read`, `hitl:write` |
| Tasks | `tasks:read`, `tasks:write`, `tasks:delete` |
| Projects | `project:read`, `project:write`, `project:delete` |
| Vulnerabilities | `vulnerability:read`, `vulnerability:write`, `vulnerability:delete` |
| WebShell | `webshell:read`, `webshell:write`, `webshell:delete` |
| C2 | `c2:read`, `c2:write`, `c2:delete` |
| MCP | `mcp:read`, `mcp:execute`, `mcp:write`, `mcp:external:execute` |
| Knowledge | `knowledge:read`, `knowledge:write`, `knowledge:delete` |
| Skills | `skills:read`, `skills:write`, `skills:delete` |
| Markdown Agents | `agents:read`, `agents:write`, `agents:delete` |
| AI testing roles | `roles:read`, `roles:write`, `roles:delete` |
| Workflows | `workflow:read`, `workflow:execute`, `workflow:write`, `workflow:delete` |
| Configuration | `config:read`, `config:write` |
| Terminal | `terminal:execute` |
| Audit | `audit:read`, `audit:delete` |
| RBAC | `rbac:read`, `rbac:write` |
| Notifications | `notification:read`, `notification:write` |
| Robots | `robot:read`, `robot:write` |
| Files | `files:read`, `files:write`, `files:delete` |
| Attack chain | `attackchain:read`, `attackchain:write` |
| FOFA | `fofa:execute` |
| OpenAPI | `openapi:read` |
| Chat groups | `group:read`, `group:write`, `group:delete` |
| Monitor | `monitor:read`, `monitor:write`, `monitor:delete` |
Important distinctions:
- `agent:execute` runs Agents but does not grant local filesystem, shell, or arbitrary configured command access.
- `agent:local-execute` is the local execution fallback and should be limited to trusted operators.
- `mcp:execute` protects the authenticated MCP HTTP entry point.
- `mcp:external:execute` allows Agent calls to external MCP tools and currently also requires `all` scope.
- `mcp:write` manages external MCP configuration; it is separate from external tool execution.
- `robot:write` manages robot configuration and the test endpoint. Chatbot conversations use the bound user or configured service account's business permissions.
---
## 5. Resource scopes
Each role has one scope:
| Scope | Meaning | Typical use |
|-------|---------|-------------|
| `all` | All resources covered by the permission | Administrator, global auditor |
| `assigned` | Explicitly assigned resources and supported parent-resource inheritance | Project member, assigned asset operator |
| `own` | Primarily resources created by/owned by the user; some resource types also support explicit assignment or parent inheritance | Personal workspace, isolated robot identity |
Users may have multiple roles. Permissions are unioned, while scopes are merged **for the same permission only**:
```text
all > assigned > own
```
Example:
```text
Global audit role: project:read + all
Personal editor: project:write + own
Effective:
project:read → all
project:write → own
```
A global read role does not widen an unrelated write permission. Authorization code must use `ScopeFor(permission)`, not the user's broadest display scope.
### Process-global restrictions
Some definitions have no owner. Their mutations require the corresponding permission with `all` scope even if the user has a `write` key:
- AI testing roles, Skills, and Markdown Agents.
- External MCP configuration.
- Robot configuration.
- Workflow definitions.
- Knowledge mutations other than search.
- Global HITL allowlist, reviewer, and audit policy.
- C2 Profile mutations.
- Some global monitor statistics.
---
## 6. Ownership, assignments, and inheritance
Use Platform permissions → Member details → Resource assignments. Directly assignable resource types include:
- `project`
- `conversation`
- `vulnerability`
- `webshell`
- `batch_task`
- `c2_listener`
A batch request accepts at most 100 resources. Duplicate grants are skipped.
Supported inheritance includes:
| Child resource | Parent access source |
|----------------|----------------------|
| Conversation | Project |
| Vulnerability | Project or related conversation |
| Message, process detail, attack chain | Conversation |
| C2 Session | Listener |
| C2 Task/file/event | Session, Task, or Listener chain |
Assigning a project therefore usually avoids assigning each conversation and vulnerability separately. The concrete route/tool server check remains authoritative.
---
## 7. Web administration workflow
### Create a user
1. Sign in as an administrator and open **Platform permissions**.
2. Create a user with username, display name, an eight-character-or-longer password, and enabled status.
3. Assign one or more platform roles.
4. For `assigned` roles, configure resource assignments.
5. Have the user sign in again and verify roles, permission count, and scope in the top-right user menu.
### Create a custom role
1. Give the role a job-oriented name and description.
2. Select `all`, `assigned`, or `own`.
3. Select only required permissions.
4. Test list, detail, mutation, deletion, Agent, and tool behavior with a test account.
5. Assign it to production users only after verification.
System roles are immutable; create a custom role instead of modifying them.
### When changes take effect
- Updating a user, password, enabled state, or role membership revokes that user's sessions; they must sign in again.
- Updating or deleting a custom role revokes all sessions; all users must sign in again.
- Robots resolve the bound user/service account on every message, so disablement and role changes affect the next message.
- Background batch jobs resolve a Principal from the task owner rather than trusting frontend state.
---
## 8. Suggested role templates
### Read-only project member
```text
Scope: assigned
dashboard:read
chat:read
project:read
vulnerability:read
files:read
attackchain:read
```
### Daily security operator
```text
Scope: assigned
agent:execute
chat:read / chat:write
project:read / project:write
vulnerability:read / vulnerability:write
tasks:read / tasks:write
files:read / files:write
hitl:read / hitl:write
```
Add `agent:local-execute` or `terminal:execute` only when local commands are required. Add individual `:delete` permissions only when deletion is part of the job.
### Robot service account
```text
Scope: own (isolated workspace) or assigned (specific projects)
agent:execute
chat:read / chat:write
optional project, vulnerability, and knowledge permissions
```
`admin` can be used as a robot service account, but exact sender allowlisting still applies. Every allowlisted sender receives full permissions and shares admin-owned data. See the [Robot guide](robot.md).
---
## 9. Agent, MCP, and robot boundaries
### Agent
The HTTP user becomes an immutable Principal propagated to single-agent, multi-agent, workflow, and tool contexts. A long-running task may survive an SSE disconnect while retaining that identity.
### Built-in MCP
Every built-in tool requires an explicit authorization policy. WebShell tools check both `webshell:read/write/delete` and the target `connection_id`; project, vulnerability, task, and C2 tools validate resource arguments as well. An unregistered built-in policy fails closed. Other local/configured tools require `agent:local-execute`.
### External MCP
Agent calls to external MCP require `mcp:external:execute` with `all` scope because an external service's resource model is not protected by local ownership and assignments.
### Robots
- `user_binding`: each platform sender binds their own RBAC user.
- `service_account`: exact allowlisted senders share one RBAC user.
- Platform signature verification authenticates message origin, not business authorization.
- Run `whoami` to inspect the effective Principal.
---
## 10. RBAC API
All requests use:
```http
Authorization: Bearer <token>
```
Management routes require `rbac:read` or `rbac:write`; the resource picker requires `rbac:write`.
| Method | Path | Purpose |
|--------|------|---------|
| GET | `/api/rbac/me` | Current user, roles, permissions, overall scope, per-permission scopes |
| GET | `/api/rbac/metadata` | Permission catalog, roles, grants, and scopes |
| GET/POST | `/api/rbac/users` | List/create users |
| PUT/DELETE | `/api/rbac/users/:id` | Update/delete a user |
| GET/POST | `/api/rbac/roles` | List/create roles |
| PUT/DELETE | `/api/rbac/roles/:id` | Update/delete a custom role |
| GET | `/api/rbac/resources?type=project&q=...` | Search assignable resources |
| GET/POST | `/api/rbac/resource-assignments` | List/create assignments |
| DELETE | `/api/rbac/resource-assignments/:id` | Revoke an assignment |
Create a user:
```bash
curl -X POST http://localhost:8080/api/rbac/users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "operator01",
"display_name": "Security Operator 01",
"password": "change-me-123",
"enabled": true,
"roles": ["operator"]
}'
```
Create a custom role:
```bash
curl -X POST http://localhost:8080/api/rbac/roles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Project Auditor",
"description": "Read assigned projects",
"scope": "assigned",
"permissions": ["chat:read", "project:read", "vulnerability:read"]
}'
```
Assign projects:
```bash
curl -X POST http://localhost:8080/api/rbac/resource-assignments \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "USER_ID",
"resource_type": "project",
"resource_ids": ["PROJECT_ID_1", "PROJECT_ID_2"]
}'
```
---
## 11. Audit and operations recommendations
- Use individual administrator accounts instead of sharing one password.
- Name custom roles by job function and document purpose/owner.
- Review high-risk permissions separately: `terminal:execute`, `agent:local-execute`, `c2:write/delete`, `webshell:write/delete`, `rbac:write`, and `config:write`.
- Periodically review `all` roles, service accounts, robot allowlists, and dormant users.
- On offboarding, disable the account first, then revoke robot bindings, assignments, and sessions.
- Monitor RBAC denials, user/role changes, resource assignments, and robot service-account execution in audit logs.
- Pair RBAC with HITL for dangerous tools; permission to invoke does not bypass approval policy.
---
## 12. Troubleshooting
### A button is missing
The frontend hides actions based on `/api/rbac/me`. Verify the required permission. Direct API calls are still rejected server-side.
### Permission exists but the resource is denied
Inspect the scope for that specific permission, not only the overall display scope. Then check owner, explicit assignment, and parent assignment.
### Role changed but the user sees old access
Role changes revoke sessions. Sign in again. Robots resolve again on the next message.
### A global mutation is denied despite `write`
Process-global definitions require the corresponding permission with `all` scope. Create a dedicated global administration role instead of widening unrelated permissions.
### Agent chat works but commands fail
`agent:execute` and `agent:local-execute` are separate. Grant local execution only when necessary and combine it with HITL, tool allowlists, and audit.
### External MCP requires global scope
The user needs `mcp:external:execute`, and that permission's scope must be `all`.
+128 -22
View File
@@ -2,7 +2,7 @@
[中文](../zh-CN/robot.md)
This document explains how to chat with CyberStrikeAI from **personal WeChat**, **DingTalk**, **Lark (Feishu)**, and **WeCom (Enterprise WeChat)** using long-lived connections or HTTP callbacks—no need to open a browser on the server. Following the steps below helps avoid common mistakes.
This guide covers **Personal WeChat, WeCom, DingTalk, Lark, Telegram, Slack, Discord, and QQ Bot**, including platform connectivity, RBAC identity binding, service-account allowlists, commands, verification, and troubleshooting.
---
@@ -15,10 +15,18 @@ This document explains how to chat with CyberStrikeAI from **personal WeChat**,
- **Personal WeChat**: Open **WeChat / iLink****Generate QR code and bind**, then scan with WeChat (see [Section 3.4](#34-personal-wechat-wechat--ilink))
- **DingTalk**: Enable and fill in Client ID / Client Secret
- **Lark**: Enable and fill in App ID / App Secret
5. Click **Apply configuration** to save (WeChat binding saves and enables automatically on success—usually no extra click needed)
6. **Restart the CyberStrikeAI process** (DingTalk/Lark: saving alone does not establish the connection; WeChat auto-restarts the iLink poll after binding—usually no manual restart needed)
5. Click **Apply configuration** to save and automatically restart the corresponding bot connection. WeChat binding saves and enables automatically on success.
Settings are written to the `robots` section of `config.yaml`; you can also edit the file directly. **After changing DingTalk or Lark config, you must restart for the long-lived connection to take effect.** Personal WeChat binding automatically writes `robots.wechat` and restarts the iLink long poll.
Settings are written to the `robots` section of `config.yaml`; you can also edit the file directly. Web-based **Apply configuration** restarts the corresponding connection automatically. Restart the CyberStrikeAI process only when editing YAML directly. Personal WeChat binding automatically writes `robots.wechat` and restarts the iLink long poll.
### Shortest path to first use
After the platform connection works, configure the business identity before sending normal prompts:
- **Multiple users**: choose User binding → each user generates a code from the top-right Web user menu → sends the bind command to the bot → runs `whoami` to verify.
- **Only you**: run `whoami` first and copy the sender ID → choose Service account → set User ID to `admin` or another RBAC user → paste the exact sender allowlist → apply configuration → run `whoami` again.
Start normal AI chat only after the response shows an authorized status and the expected effective identity.
---
@@ -82,7 +90,7 @@ If you only have a **custom bot** Webhook URL (`oapi.dingtalk.com/robot/send?acc
- In CyberStrikeAI: System settings → Robot settings → DingTalk.
- Enable “Enable DingTalk robot”.
- Paste the Client ID and Client Secret from step 3.
- Click **Apply configuration**, then **restart CyberStrikeAI**.
- Click **Apply configuration**; CyberStrikeAI restarts the DingTalk connection automatically.
---
@@ -105,7 +113,7 @@ If you only have a **custom bot** Webhook URL (`oapi.dingtalk.com/robot/send?acc
| App Secret | From Lark open platform app credentials |
| Verify Token | Optional; for event subscription |
**Lark setup in short**: Log in to [Lark Open Platform](https://open.feishu.cn) → Create an enterprise app → In “Credentials and basic info” get **App ID** and **App Secret** → In “Application capabilities” enable **Robot** and the right permissions → Add **event subscription** and **permissions** below → Publish the app → Enter App ID and App Secret in CyberStrikeAI robot settings → Save and **restart** the app.
**Lark setup in short**: Log in to [Lark Open Platform](https://open.feishu.cn) → Create an enterprise app → In “Credentials and basic info” get **App ID** and **App Secret** → In “Application capabilities” enable **Robot** and the right permissions → Add **event subscription** and **permissions** below → Publish the app → Enter App ID and App Secret in CyberStrikeAI robot settings → **Apply configuration**.
**Event subscription**
The long-lived connection only receives message events if you subscribe to them. In the apps **Events and callbacks** (事件与回调) → **Event subscription** (事件订阅), add the event **Receive message** (**im.message.receive_v1**). Without it, the connection succeeds but no message events are delivered (no logs when users send messages).
@@ -272,12 +280,79 @@ In **Permission management** (权限管理), enable the following (names and ide
---
## 4. Bot commands
## 4. RBAC authorization and bot commands
Platform credentials and callback signatures authenticate the messaging platform. CyberStrikeAI RBAC determines what the sender can actually do. Each bot instance uses one authorization mode.
### 4.1 Choose an authorization mode
| Scenario | Recommended mode | Identity and data behavior |
|----------|------------------|----------------------------|
| Shared WeCom, Lark, DingTalk, or Slack bot | `user_binding` | Each sender binds their own Web user; permissions and resources remain isolated |
| Personal WeChat, single-user bot, fixed automation entry | `service_account` | Allowlisted senders share the configured RBAC user's permissions and owned resources |
Both modes resolve user status, roles, per-permission scope, and resource assignments before every message. Basic AI chat requires:
```text
agent:execute
chat:read
chat:write
```
Grant project, role, local execution, WebShell, C2, or MCP permissions only when those features are required. Conversation deletion also requires `chat:delete`.
### 4.2 User-binding mode (default)
Administrator:
1. Open System settings → Robot settings → select a platform.
2. Set Authorization policy to `user_binding` and apply the configuration.
Each user:
1. Sign in to the Web UI and open the top-right user menu → **Bind robot account**.
2. Generate a binding code; a five-minute countdown starts.
3. Send the full command to the target bot, for example `bind 7C6E-BD4C`.
4. Send `whoami` and confirm the effective RBAC identity is their own Web user.
Codes are stored only as hashes and are single-use. When the countdown ends, the UI marks the code expired, disables copying, and refreshes the binding list; the server also rejects it. Generating a new code immediately invalidates the previous unused code. Users can send `unbind` or revoke a binding from the Web dialog.
### 4.3 Service-account mode
1. Connect the bot to its messaging platform.
2. Have each intended sender run `whoami` and copy the exact sender ID. For Personal WeChat it usually resembles `xxxx@im.wechat`; never substitute `ilink_bot_id` or configured `ilink_user_id`.
3. In Robot settings, select `service_account`.
4. Enter the RBAC **User ID**, not its display name. `admin` is allowed; every allowlisted sender then receives full platform permissions and the UI shows a red warning.
5. Add one exact sender ID per line. Matching is case-sensitive and `*` wildcards are rejected.
6. Apply configuration and run `whoami` again to verify the effective user, roles, and scope.
Example:
```yaml
robots:
wechat:
auth:
mode: service_account
service_user_id: admin
allowed_external_users:
- "o9cq806s32Sm2_kyOmkyaV7Rn1lU@im.wechat"
```
Service-account mode rejects `bind` and `unbind`. All allowlisted senders share conversations, projects, and other resources owned by the service account. Use `user_binding` when that sharing is undesirable.
### 4.4 Inspect the effective identity
Send `whoami`. The response includes platform, exact sender ID, authorization mode and status, effective RBAC user and ID, roles, scope, and permission count. A non-allowlisted sender sees only the denial status and no service-account details.
### 4.5 Command list
Send these **text commands** to the bot on any connected platform (text only):
| Command | Description |
|---------|-------------|
| **绑定 \<code\>** or **bind \<code\>** | Bind the verified platform sender to the RBAC user that generated the code |
| **解绑** or **unbind** | Remove the current platform identity binding |
| **身份** or **whoami** | Show sender ID, authorization mode, binding status, and the effective RBAC user, roles, and scope |
| **帮助** (help) | Show command help |
| **列表** or **对话列表** (list) | List all conversation titles and IDs |
| **切换 \<conversationID\>** or **继续 \<conversationID\>** | Continue in the given conversation |
@@ -292,6 +367,8 @@ Send these **text commands** to the bot on any connected platform (text only):
Any other text is sent to the AI as a user message, same as in the web UI (e.g. penetration testing, security analysis).
Group messages are authorized as the actual sender, never as a group ID. In service-account mode, explicitly allowlisted senders intentionally share the configured account.
---
## 5. How to use (do I need to @ the bot?)
@@ -310,14 +387,17 @@ Summary: **Personal WeChat and direct chat**—just send; **DingTalk/Lark in a g
1. CyberStrikeAI web UI → System settings → Robot settings → **WeChat / iLink****Generate QR code and bind**.
2. Scan with WeChat and confirm (enter pairing code on the web page if prompted).
3. After binding, send “帮助” in the WeChat private chat to test.
3. Send `whoami` in the WeChat private chat and copy the sender ID.
4. Choose `user_binding`, or configure `service_account` with the RBAC user and exact sender allowlist.
5. Apply configuration, run `whoami` again, then send a normal message.
**DingTalk / Lark**
1. **In the open platform**: Complete app creation, copy credentials, enable the bot (DingTalk: **Stream mode**), set permissions, and publish (Section 3).
2. **In CyberStrikeAI**: System settings → Robot settings → Enable the platform, paste Client ID/App ID and Client Secret/App Secret → **Apply configuration**.
3. **Restart the CyberStrikeAI process** (otherwise the long-lived connection is not established).
4. **On your phone**: Open DingTalk or Lark, find the bot (direct chat or @ in a group), send “帮助” or any message to test.
3. **Choose authorization**: use `user_binding` for multiple users, or configure a service account and exact allowlist for a dedicated bot.
4. **Apply configuration**; the Web UI restarts the corresponding connection automatically.
5. **On your phone**: Open the bot, run `whoami` first, then send a normal message.
If the bot does not respond, see **Section 9 (troubleshooting)** and **Section 10 (common pitfalls)**.
@@ -331,6 +411,11 @@ Example `robots` section in `config.yaml`:
robots:
wechat: # Personal WeChat iLink (auto-filled after QR bind; usually no manual edit)
enabled: true
auth:
mode: service_account
service_user_id: admin
allowed_external_users:
- "exact sender ID copied from whoami"
bot_token: "your_bot_token@im.bot:..."
ilink_bot_id: "your_bot_id@im.bot"
ilink_user_id: "your_user_id@im.wechat"
@@ -339,10 +424,14 @@ robots:
bot_agent: "CyberStrikeAI/1.0"
dingtalk:
enabled: true
auth:
mode: user_binding
client_id: "your_dingtalk_app_key"
client_secret: "your_dingtalk_app_secret"
lark:
enabled: true
auth:
mode: user_binding
app_id: "your_lark_app_id"
app_secret: "your_lark_app_secret"
verify_token: ""
@@ -372,7 +461,7 @@ robots:
sandbox: true
```
After changing DingTalk/Lark/WeCom/Telegram/Slack/Discord/QQ settings, **Apply configuration** restarts the corresponding connections. Personal WeChat QR binding saves and restarts automatically.
Authorization is configured independently per platform; omitting `auth` defaults to `user_binding`. **Apply configuration** restarts the corresponding connections. Restart the process only after editing YAML directly. Personal WeChat QR binding saves and restarts automatically.
---
@@ -380,20 +469,24 @@ After changing DingTalk/Lark/WeCom/Telegram/Slack/Discord/QQ settings, **Apply c
You can verify bot logic with the **test API** (no DingTalk/Lark client needed):
1. Log in to the CyberStrikeAI web UI (so you have a session).
2. Call the test endpoint with curl (include your session Cookie):
1. Sign in with an account that has global `robot:write` permission and obtain a Bearer token.
2. Call the test endpoint with curl:
```bash
# Replace YOUR_COOKIE with the Cookie from your browser (F12 → Network → any request → Request headers → Cookie)
# Adjust the URL, username, and password for your deployment
TOKEN=$(curl -s -X POST "http://localhost:8080/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"YOUR_PASSWORD"}' | jq -r '.token')
curl -X POST "http://localhost:8080/api/robot/test" \
-H "Content-Type: application/json" \
-H "Cookie: YOUR_COOKIE" \
-H "Authorization: Bearer $TOKEN" \
-d '{"platform":"dingtalk","user_id":"test_user","text":"帮助"}'
```
If the JSON response contains `"reply":"【CyberStrikeAI 机器人命令】..."`, command handling works. You can also try `"text":"列表"` or `"text":"当前"`.
If the JSON response contains `"reply":"【CyberStrikeAI 机器人命令】..."`, command handling works. `help`, `version`, and `whoami` work before binding. `list`, `current`, and normal AI messages enforce RBAC: the test `platform + user_id` must already be bound or exactly match the service-account allowlist.
API: `POST /api/robot/test` (requires login). Body: `{"platform":"optional","user_id":"optional","text":"required"}`. Response: `{"reply":"..."}`.
API: `POST /api/robot/test` (requires global `robot:write`). Body: `{"platform":"optional","user_id":"optional","text":"required"}`. Response: `{"reply":"..."}`. This endpoint simulates bot business logic only; it does not validate a third-party callback signature or long-lived connection.
---
@@ -407,7 +500,7 @@ Check in this order:
Robot settings should show “Connected” or a bound Bot ID; `robots.wechat.bot_token` in `config.yaml` must not be empty.
2. **Enabled?**
Confirm “Enable WeChat robot” is checked; restart CyberStrikeAI if you just changed settings.
Confirm “Enable WeChat robot” is checked and click **Apply configuration** if you just changed settings.
3. **Application logs**
- On startup: `微信 iLink 长轮询已启动`;
@@ -430,8 +523,8 @@ Check in this order:
1. **Client ID / Client Secret match the open platform exactly**
Copy from “Credentials and basic info”; avoid typing. Watch **0** vs **o** and **1** vs **l** (e.g. `ding9gf9tiozuc504aer` has **504**, not 5o4).
2. **Did you restart after saving?**
The long-lived connection is created at **startup**. “Apply configuration” only updates the config file; you **must restart the CyberStrikeAI process** for the DingTalk connection to start.
2. **Did you apply the configuration?**
Web changes require **Apply configuration**, which restarts the corresponding connection automatically. Restart the process only after editing `config.yaml` directly.
3. **Application logs**
- On startup you should see: `钉钉 Stream 正在连接…`, `钉钉 Stream 已启动(无需公网),等待收消息`.
@@ -441,6 +534,15 @@ Check in this order:
4. **Open platform**
The app must be **published**. Under “Robot” you must enable **Stream** for receiving messages (HTTP callback only is not enough). Permission management must include robot receive/send message permissions.
### 9.3 Reply says unbound, sender denied, or permission missing
1. Run `whoami` and inspect the authorization mode and status.
2. In `user_binding`, generate a code from the top-right Web user menu and send the complete bind command from the same platform identity. Regenerate expired or already-used codes.
3. In `service_account`, copy the exact sender ID from `whoami` into that platform's allowlist. Preserve case, tenant prefixes, and suffixes such as `@im.wechat`.
4. If an effective user is shown but permissions are missing, grant at least `agent:execute`, `chat:read`, and `chat:write` for normal AI chat.
5. A missing or disabled service user is rejected when applying configuration.
6. If `admin` is denied, the usual cause is an allowlist mismatch—not insufficient admin permissions.
---
## 10. Common pitfalls
@@ -448,7 +550,11 @@ Check in this order:
- **Personal WeChat vs WeCom**: Personal WeChat uses `robots.wechat` + web QR bind; WeCom uses `robots.wecom` + admin callback URL—they are completely different.
- **WeChat QR expired**: QR codes last ~5 minutes; regenerate instead of reusing an old one.
- **Wrong bot type**: The “Custom” bot added in a DingTalk **group** (Webhook + sign secret) **cannot** be used for two-way chat. Only the **enterprise internal app** bot from the open platform is supported.
- **Saved but not restarted**: After changing DingTalk/Lark robot settings you **must restart** the app (WeChat QR bind restarts the connection automatically).
- **Configuration not applied**: Click **Apply configuration** after Web changes; connections restart automatically. A process restart is needed only for direct YAML edits.
- **Bot ID used as sender ID**: Copy the sender ID from `whoami`; do not use `ilink_bot_id`, configured `ilink_user_id`, a group ID, or a display name.
- **Reusing an expired code**: Codes last five minutes and are single-use; generating a new code immediately invalidates the old one.
- **Assuming service-account users are isolated**: All allowlisted senders share that account's conversations and owned resources. Use `user_binding` for isolation.
- **Assuming admin removes the allowlist**: It does not. The sender must still match exactly, but every matching sender gets full permissions.
- **Client ID typo**: If the platform shows `504`, use `504` (not `5o4`); prefer copy/paste.
- **DingTalk: only HTTP callback, no Stream**: This app receives messages via **Stream**. In the open platform, message reception must be **Stream mode**.
- **App not published**: After changing the bot or permissions in the open platform, **publish a new version** under “Version management and release”, or changes wont apply.
@@ -459,5 +565,5 @@ Check in this order:
- All platforms: **text messages only**; other types (e.g. image, voice) are not supported and may be ignored.
- Personal WeChat: **private chat only**—group @-bot is not supported.
- Conversations are shared with the web UI: conversations created from the bot appear in the web “Conversations” list and vice versa.
- Bot data is shared with the web UI: under `user_binding` it belongs to the bound user; under `service_account` it belongs to the service account and is shared by allowlisted senders.
- Bot execution uses the same **Eino single/multi-agent** path as the web UI (`ProcessMessageForRobot`, with progress callbacks and process details stored in the DB); only the final reply is sent back to personal WeChat/DingTalk/Lark/WeCom in one message (no SSE). Default: `robot_default_agent_mode: eino_single`.