Files
awoooi/docs/adr/ADR-087-auto-approve-security-hardening.md
OG T ba8cf6105d docs(adr): ADR-086 Telegram UI 清洗規範 + ADR-087 AutoApprove kubectl 閘門
ADR-086: Telegram 通知卡片 UI 清洗規範
- _parse_debate_summary() 設計決定與各 TYPE 欄位清洗規則
- TYPE-3 鍵盤重構:批准/拒絕永遠第一行
- 技術債:_parse_debate_summary 提升模組層級(P1-1)

ADR-087: AutoApprove 安全強化 — kubectl 強制執行閘門
- 條件 1d 設計:_raw_action 語意 + NO_EXECUTABLE_ACTION reason
- Solver Nemo 格式 kubectl 驗證
- 降級指令改為真實 kubectl 唯讀調查
- min_trust_score=0 保留理由記錄(TrustEngine 記憶體持久化技術債)
- P0-2 風險記錄:kubectl exec 未加入 _DESTRUCTIVE_PATTERNS

2026-04-17 ogt + Claude Sonnet 4.6(亞太): Session 技術債清理

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:25:34 +08:00

119 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-087: AutoApprove 安全強化 — kubectl 強制執行閘門
**狀態**: 已接受
**日期**: 2026-04-17
**作者**: ogt + Claude Sonnet 4.6
**關聯**: ADR-070全自動 AIOps 閉環、ADR-082多 Agent 協作)
---
## 背景
Phase 2 多 Agent 協作ADR-082Solver Agent 透過 OpenClaw 的 openclaw_nemo provider 產出修復方案時,有兩條路徑:
1. **標準格式**`{"candidates": [{"action": "kubectl rollout restart ...", ...}]}`
2. **Nemo 格式**`{"action_title": "重啟 Crash Looping Pod", "confidence": 0.85}`
Nemo 格式的 `action_title` 是自然語言描述,不是可執行的 kubectl 指令。
### 問題一auto_approve 誤放行自然語言 action
原有條件:
- 條件 1c`action` 為空 → 拒絕
- 條件 1d未驗證 action 是否可執行
結果Solver Nemo 路徑輸出「重啟 Crash Looping Pod」→ 條件 1c 通過(非空)→ 自動批准 → `kubectl_command` 欄位為空 → 實際無法執行 → incident 卡在 INVESTIGATING 狀態。
### 問題二Solver 降級動作為自然語言
`_default_action_for_category()` 回傳:
- `"restart_pod"``"check_disk_usage"` 等非 kubectl 字串
這些字串通過條件 1c非空但無法被執行層使用。
---
## 決策
### 1. 條件 1dkubectl 格式強制閘
位置:`auto_approve.py:evaluate()`,在條件 1c 之後、條件 2 之前。
```python
# 條件 1d: 自然語言描述不可自動執行
_raw_action = proposal_data.get("action", "") or "" # 原始值,不 fallback
_kubectl_cmd = proposal_data.get("kubectl_command", "") or ""
_has_kubectl = "kubectl" in _raw_action.lower() or "kubectl" in _kubectl_cmd.lower()
if not _has_kubectl:
return self._reject(
reason=AutoApproveReason.NO_EXECUTABLE_ACTION,
detail=f"Action '{_raw_action[:60]}' is natural language — no kubectl command",
...
)
```
**設計要點**
- 使用 `proposal_data.get("action", "")` 原始值(非 line 232 已 fallback 的 `action` 變數),避免 fallback 語意混淆Code Review P0-1
- 新增 `AutoApproveReason.NO_EXECUTABLE_ACTION` enum 值,與 `NO_PLAYBOOK`(無匹配 Playbook語意分離防止污染 KM 飛輪學習資料分類Code Review P1-2
### 2. Solver Nemo 格式kubectl 驗證
位置:`solver_agent.py:_extract_candidates()`
```python
if "action_title" in parsed and "candidates" not in parsed:
action_title = str(parsed.get("action_title", ""))
if "kubectl" not in action_title.lower():
return [] # → 觸發 _degraded_plan輸出真實 kubectl 調查指令
```
### 3. 降級指令改為真實 kubectl
`_default_action_for_category()` 改為按類別回傳唯讀調查指令:
| Category | 降級指令 |
|----------|---------|
| pod/kube/crash | `kubectl get pods -n awoooi-prod -o wide` |
| disk/storage/pvc | `kubectl exec -n awoooi-prod deployment/postgresql -- df -h` |
| cpu/load | `kubectl top pods -n awoooi-prod --sort-by=cpu` |
| memory/oom | `kubectl top pods -n awoooi-prod --sort-by=memory` |
| network/connect | `kubectl get services -n awoooi-prod` |
| default | `kubectl get pods -n awoooi-prod` |
**設計原則**降級指令均為唯讀調查操作無副作用blast_radius=20
---
## min_trust_score 設計決定
`min_trust_score: int = 0` 保持不變。
**理由**TrustEngine 資料儲存於記憶體(`_trust_records` dictPod 重啟後歸零。若將門檻提高至 0.8,每次 Pod 重啟後所有動作都無法自動執行,直到累積足夠歷史記錄。這在生產環境中不可接受。
**正確方向**:將 TrustEngine 持久化至 PostgreSQL已列為 Phase 3.5 技術債)。
---
## 後果
- 自然語言 action 不再通過 auto_approve強制走 TYPE-3 人工審核
- Solver 降級路徑輸出真實 kubectl 調查指令,可被 auto_approve 正確評估
- `NO_EXECUTABLE_ACTION` reason 與 `NO_PLAYBOOK` 區分KM 飛輪學習資料分類正確
---
## 已知風險 (P0-2 — 下次 Security Review)
`kubectl exec` 指令(降級路徑中的 disk 類別)被允許通過條件 1d`kubectl exec` 可以在容器內執行任意命令。目前降級指令固定為 `df -h`(唯讀),但若未來 LLM 輸出包含 `kubectl exec` 的高風險變體,現有 `_DESTRUCTIVE_PATTERNS` 不包含 `exec` 關鍵字,可能漏過。
**建議**:下次 Security Review 時評估是否將 `kubectl exec` 加入 `_DESTRUCTIVE_PATTERNS` 或獨立 allow-list。
---
## 相關 Commits
| Commit | 說明 |
|--------|------|
| `93205ce` | P1 kubectl gate + P2 Nemo path 強制 |
| `fb225c5` | Code Review P0-1 action fallback + P1-2 NO_EXECUTABLE_ACTION enum |