feat(adr-076): Task 2.2 + 2.3 — 規則擴充 + kubectl 注入防護
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Task 2.2: alert_rules.yaml 新增 3 類規則 (priority 125-127)
- gitea_down: Gitea CI/CD 下線 → NO_ACTION (priority 125, critical)
- ssl_cert_expiring: SSL 憑證到期 → NO_ACTION (priority 126, medium)
- external_site_down: MoWoooWork/Dev/Blackbox probe → NO_ACTION (priority 127, medium)
規則總數: 21 → 24
Task 2.3: alert_rule_engine.py kubectl 注入防護
- _RULE_ENGINE_DESTRUCTIVE_RE: 阻擋 delete pvc/namespace/statefulset/deployment,
drain/cordon, --replicas=0, rm -rf, DROP TABLE, $() 反引號
- validate_kubectl_command(): 公開 API,SSH 指令/空字串直接通過
- match_rule() 整合: 變數替換後驗證,阻擋時清空 + log warning
- test_alert_rule_engine_validation.py: 34 tests (100% 通過)
測試: 776 passed, 26 skipped, 0 failed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,51 @@ _generating: set[str] = set()
|
||||
# Redis 分散式鎖 TTL (秒),覆蓋 Ollama + Gemini 最長生成時間
|
||||
_RULE_GEN_LOCK_TTL = 120
|
||||
|
||||
# ── kubectl 注入防護 (Task 2.3, ADR-076, 2026-04-14) ─────────
|
||||
# 對齊 auto_approve._DESTRUCTIVE_PATTERNS + decision_manager._ALLOWED_KUBECTL_PATTERN
|
||||
# 目標: 規則 YAML 中的 kubectl_command 在變數替換後若含下列破壞性模式 → 清空並告警
|
||||
_RULE_ENGINE_DESTRUCTIVE_RE = re.compile(
|
||||
r"(kubectl\s+delete\s+(pvc|namespace|statefulset|deployment)" # 破壞性 K8s 刪除
|
||||
r"|kubectl\s+(drain|cordon)" # 節點驅逐/封鎖
|
||||
r"|--replicas=\s*0\b" # 縮容至零
|
||||
r"|rm\s+-[rf]{1,2}\s" # rm -rf
|
||||
r"|\bdrop\s+(table|database)\b" # SQL 破壞性 DDL
|
||||
r"|\$\([^)]{0,200}\)" # shell 命令替換 $(...)
|
||||
r"|`[^`]{0,200}`" # 反引號替換
|
||||
r")",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
# ── kubectl 注入防護 公開 API ───────────────────────────────
|
||||
|
||||
|
||||
def validate_kubectl_command(command: str) -> bool:
|
||||
"""
|
||||
kubectl 注入安全驗證(Task 2.3, ADR-076)。
|
||||
|
||||
Returns:
|
||||
True — 指令安全,可執行
|
||||
False — 含破壞性模式,呼叫方應清空指令並記錄 warning
|
||||
|
||||
通過條件(直接 True):
|
||||
- 空字串 — 無動作規則
|
||||
- "ssh ..." 開頭 — SSH 層指令,不走 kubectl 路徑
|
||||
|
||||
阻擋條件(返回 False):
|
||||
- kubectl delete pvc/namespace/statefulset/deployment — 破壞性刪除
|
||||
- kubectl drain / cordon — 節點驅逐(業務衝擊)
|
||||
- --replicas=0 — 縮容至零(服務停止)
|
||||
- rm -rf — 主機層破壞
|
||||
- DROP TABLE/DATABASE — SQL 破壞性 DDL
|
||||
- $(...) 或反引號 — Shell 命令注入
|
||||
"""
|
||||
if not command:
|
||||
return True
|
||||
if command.strip().startswith("ssh "):
|
||||
return True
|
||||
return not bool(_RULE_ENGINE_DESTRUCTIVE_RE.search(command))
|
||||
|
||||
|
||||
# ── 變數提取 ────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -211,12 +256,23 @@ def match_rule(alert_context: dict) -> dict[str, Any] | None:
|
||||
for o in resp.get("optimization", [])
|
||||
]
|
||||
|
||||
# Task 2.3: kubectl 注入防護 — 變數替換後驗證,阻擋破壞性模式
|
||||
kubectl_command = _fill(resp.get("kubectl_command", ""), vars)
|
||||
if not validate_kubectl_command(kubectl_command):
|
||||
logger.warning(
|
||||
"rule_kubectl_command_blocked",
|
||||
rule_id=matched_rule["id"],
|
||||
reason="destructive_pattern_detected",
|
||||
command_snippet=kubectl_command[:80],
|
||||
)
|
||||
kubectl_command = ""
|
||||
|
||||
return {
|
||||
"rule_id": matched_rule["id"],
|
||||
"action_title": _fill(resp["action_title"], vars),
|
||||
"description": _fill(resp["description"], vars),
|
||||
"suggested_action": resp["suggested_action"],
|
||||
"kubectl_command": _fill(resp["kubectl_command"], vars),
|
||||
"kubectl_command": kubectl_command,
|
||||
"target_resource": vars["target"],
|
||||
"namespace": vars["namespace"],
|
||||
"risk_level": risk,
|
||||
|
||||
Reference in New Issue
Block a user