diff --git a/backend/agent_tools.py b/backend/agent_tools.py index 514c1de..fc414ff 100644 --- a/backend/agent_tools.py +++ b/backend/agent_tools.py @@ -133,7 +133,7 @@ SHELL_READ_ONLY_COMMANDS: dict[str, set[str] | None] = { # etcdctl 单段式只读 verb _ETCDCTL_READ_VERBS = {"get", "watch", "version", "lock", "lease", "move-leader", "leader"} # etcdctl 单段式写 verb (需人工审批) -_ETCDCTL_WRITE_VERBS = {"put", "del", "delete", "compact", "txn", "snapshot"} +_ETCDCTL_WRITE_VERBS = {"put", "del", "delete", "compact", "txn", "snapshot", "defrag"} # etcdctl 两段式 (verb, subverb) 只读组合 _ETCDCTL_READ_SUBVERBS = { "endpoint": {"status", "health", "hashkv"}, @@ -154,6 +154,8 @@ _ETCDCTL_WRITE_SUBVERBS = { } # etcdutl snapshot 只读子命令 _ETCDUTL_SNAPSHOT_READ = {"status", "hash"} +# etcdutl snapshot 写子命令 (需人工审批) +_ETCDUTL_SNAPSHOT_WRITE = {"restore", "make"} # 系统修改命令白名单:需要人工审批 SHELL_WRITE_COMMANDS: dict[str, set[str] | None] = { @@ -233,7 +235,9 @@ def classify_shell_command(command: str) -> CommandDecision: if ev == "snapshot": if esub in _ETCDUTL_SNAPSHOT_READ: return CommandDecision("read", False, ev, parts[1:]) - return CommandDecision("write", True, ev, parts[1:]) + if esub in _ETCDUTL_SNAPSHOT_WRITE: + return CommandDecision("write", True, ev, parts[1:]) + raise ValueError(f"etcdutl snapshot 不支持子命令: {esub}") if ev == "version": return CommandDecision("read", False, ev, parts[1:]) raise ValueError(f"etcdutl 不支持该子命令: {ev}")