ai-agent / sre / observability / security / mcp

生产排障 Agent 的安全边界:为什么只读 SSH 不是默认方案

生产排障 Agent 的安全边界:为什么只读 SSH 不是默认方案

Codex、Claude Code、Gemini CLI 这类 agent 已经能在代码库里读上下文、跑命令、整理证据、提出假设。把它们带进生产排障,不是很远的事。

容易走偏的做法,是给 agent 建一个只读 Linux 账号,让它 SSH 到生产机器上查问题。

这个方案启动很快,也显得克制。没有 sudo,不改文件,不重启服务。可生产环境里的“读”从来不是简单权限。日志、环境变量、配置、core dump、备份、/proc、Kubernetes 对象,很多东西只要能读,就能带出凭证、客户数据或内部拓扑。

日常入口不该是普通 SSH shell,而应放在观测系统、生产日志查询能力和 incident 上下文上。agent 先读 SLO、告警、metrics、logs、traces、发布记录、runbook 和服务拓扑,再通过受限 MCP 调用一组语义化诊断工具。SSH 可以保留,但要当 break-glass,用 forced command、allowlist、短期凭证和审计系统包住。

这里的“观测系统”不能只理解成 SLO 和告警。很多疑难 bug 不会立刻打爆 SLO,甚至不会触发 paging。它们只在某个租户、某类订单、某个浏览器版本、某种数据形态或某条异步链路里出现。定位这类问题,生产日志、trace、业务事件和请求时间线都可能是必要证据。问题不是能不能查日志,而是谁可以查、按什么范围查、能看到哪些字段、输出到哪里、事后如何审计。

模型能力只是前提。生产系统要先回答几个更无聊也更要命的问题:权限在哪里收口,数据在哪里脱敏,动作在哪里审批,事后能不能复盘。

借用 Google SRE 的自动化框架

Google SRE 的 The Evolution of Automation at Google 很适合拿来校准这个问题。那篇文章没有把自动化当成信仰,而是当成工程工具看待:自动化能带来一致性、平台化、更快的修复和更少的重复劳动,也会引入抽象泄漏、系统性误操作,以及人对系统理解的退化。

生产排障 agent 也要放在这个框架里看。它不是 SRE 的替代品,也不是“让模型登录机器”的理由。它更像一个取证和压缩上下文的自动化层:把 incident 或疑难 bug 期间分散在十几个系统里的证据收拢,按服务、时间线和假设组织起来,让人少花时间翻系统,多花时间判断。

Google SRE 的 Monitoring Distributed Systems 还给了一个约束:监控要围绕症状和用户体验,不要堆满底层原因猜测。对用户可见服务,延迟、流量、错误和饱和度是经典的 four golden signals。Service Level Objectives 则把可靠性管理放在 SLI、SLO 和目标失守后的反应机制上。

这并不等于所有问题都从 SLO 开始。更好的边界是:agent 不从机器细节开始。第一层事实要么是服务级证据,要么是请求级证据。前者包括哪个 SLO 受损、哪条用户路径受影响、错误预算消耗到什么程度、告警对应什么症状;后者包括 correlation id、trace id、时间窗口、业务对象、错误日志模式、最近发布和相关配置变化。

生产排障不是一个动作

“排障”这个词太粗。拆开以后,agent 该插在哪里会清楚很多。

阶段目标Agent 的合适位置主要风险
检测发现 SLO 或症状异常读取告警和上下文不应替代监控链路
取证收集 metrics、logs、traces、发布记录适合可能读到敏感数据
假设排列可能的故障路径适合幻觉和过早收敛
决策判断是否回滚、扩容、切流量只能辅助责任边界必须清楚
执行改变生产状态默认不适合误操作影响最大
复盘生成 timeline、证据和 action item适合不能把猜测写成事实

第一版生产排障 agent 先集中在取证、假设和复盘。检测仍由 Prometheus、Cloud Monitoring、Datadog、Sentry、ARMS/SLS、Alertmanager 这类系统负责。执行仍由人或已有自动化系统负责。

这个边界并不保守。它只是把 agent 放在当前最有价值、也最容易控制风险的位置。

还要把 incident 和疑难 bug 分开。incident 通常从告警、SLO 或用户影响开始,目标是快速止血。疑难 bug 可能从客服工单、用户反馈、灰度验证、数据异常或某个业务对象开始,目标是还原路径、缩小触发条件、找到代码或数据假设里的错位。后一类问题更依赖生产日志查询,但也不需要普通 shell。

公开实践在避开什么

Google Cloud 的 Gemini Cloud Assist 把 AI 辅助运维放在 logs、metrics、traces、配置、代码和告警上下文里,并强调用户授权。Google 的 SAIF agent 安全框架 说得更直接:agent 会处理不可信上下文,推理循环可能被间接 prompt injection 影响,工具权限要最小化,输出渲染本身也是安全边界。它列出的控制点包括 agent permissions、user control、agent observability、output validation 和 sanitization。

阿里的公开资料也不是“让模型登录机器”。开源的 SREWorks 是云原生 DataOps & AIOps 平台。论文 MicroHECL 用服务调用图、RT/EC/QPS 异常、传播链和相关性排序做微服务根因定位。CloudRCA 把 KPI、日志和拓扑放进知识增强的 Bayesian Network,用来做云产品故障诊断。

读这些公开材料,能看到一个朴素结论:先把证据结构化。指标、日志、链路、拓扑、变更、服务关系、SLO 和可控的日志查询接口是推理基础。通用生产 shell 不是。

蚂蚁/支付宝的具体 LLM agent 生产排障方案,目前没有足够强的一手公开资料。不能把猜测写成案例。能稳妥借鉴的是金融级系统的安全标准:最小权限、数据隔离、审计、审批和敏感信息控制必须前置。这个标准本身就排斥普通只读 shell 作为默认入口。

能力层级要显式

Google SRE 讨论自动化演进时,把手工命令、脚本、系统外自动化和系统内部自治机制分开看。生产排障 agent 也要这样分层。否则团队很容易从“看一下日志”滑到“修一下生产”。

层级能力典型接口第一版是否适合
L0只读文档和 runbook文档库、postmortem、告警说明适合
L1读取 incident 上下文工单、告警、dashboard 链接、发布记录适合
L2读取观测和日志数据Prometheus、Sentry、日志平台、trace 平台 MCP适合
L3受限主机诊断host diagnostic MCP可以试点
L4break-glass SSHforced command wrapper只适合应急
L5审批式修复回滚、扩容、切流量的固定 workflow需要演练后引入
L6自主修复agent 自己判断并执行生产动作不适合第一版

每升一级,都要回答三个问题:

  • agent 会多看到什么数据?
  • agent 会多触发什么动作?
  • 如果它错了,影响范围有多大?

答不清楚,就不要升级权限。

“只读”不是安全边界

“只读账号”听起来安全,因为它没有写权限。但生产系统里,读权限本身就很敏感。

Kubernetes RBAC 是一个好例子。Kubernetes 内置的 view role 能读大部分 namespace 对象,但默认不允许读取 Secrets,因为读取 Secrets 可能拿到 ServiceAccount 凭证并造成权限提升。成熟系统不会把 read-only 等同于 safe-to-read。

Linux 主机上也一样。一个只读账号可能读到:

  • 原始日志里的 token、session、手机号、邮箱、用户输入。
  • 服务配置里的数据库地址、内部域名、feature flag。
  • /proc/<pid>/environ 里的环境变量。
  • core dump、heap dump、备份文件。
  • shell history 和临时文件。
  • Nginx、systemd、应用日志里的请求路径、header 或内部错误。

这些都不需要写权限。只要能读,就可能出事。

所以权限设计不能只问“这个账号能不能写”。还要问:这个工具会不会读到不该离开当前安全边界的数据?

SSH 的问题是接口太宽

SSH 本身没有问题。普通 shell 才是问题。它不是一个窄接口。

如果给 agent 一个普通 Linux shell,即使账号不能 sudo,也很难回答这些问题:

  • 哪些命令被允许?
  • 哪些目录永远不能读?
  • 输出是否经过脱敏?
  • 一次命令最多能跑多久?
  • 一次最多输出多少内容?
  • 是否允许端口转发?
  • 是否允许 agent forwarding?
  • 是否允许 TTY?
  • 是否记录了原始命令、参数、输出摘要和 incident ID?
  • 是否能把一次排障会话完整复盘?

OpenSSH 的 sshd 手册 支持在 authorized_keys 上配置 command=restrictno-ptyno-agent-forwardingno-port-forwardingno-user-rcno-X11-forwarding。forced command 可以通过 SSH_ORIGINAL_COMMAND 拿到原始请求命令,然后由 wrapper 决定是否允许。

这可以把 SSH 包成受控入口。安全边界在 wrapper:

ssh key
  -> forced command wrapper
  -> parse SSH_ORIGINAL_COMMAND
  -> command allowlist
  -> argument validation
  -> path denylist
  -> timeout and output cap
  -> redaction
  -> audit
  -> return bounded result

这个模式适合 break-glass,不适合日常入口。原因很简单:wrapper 最后会长成一个临时 MCP,只是协议更粗,输出更难结构化,策略更难复用。

MCP 的价值在工具边界

MCP 也不是安全魔法。暴露 run_shell(command) 的 MCP,和给 shell 没有本质区别。

MCP 的优势在于可以把能力设计成语义化工具:

get_service_slo(service, window)
get_alert_context(alert_id)
get_recent_deploys(service, window)
query_service_metrics(service, metric, window)
search_sanitized_logs(service, query, window, limit)
get_log_schema(service)
get_request_timeline(correlation_id, window)
get_error_examples(service, signature, window, limit)
compare_log_patterns(service, baseline_window, incident_window)
get_trace_error_summary(service, window)
get_runbook(service)
get_host_health(host)

危险接口通常是这些:

run_shell(command)
read_file(path)
kubectl(args)
sql(query)
curl(url)

前一组工具表达排障意图。后一组工具表达任意能力。差别不在命名风格,而在权限模型。

MCP 官方的 security best practices 已经列出 confused deputy、token passthrough、SSRF、session hijacking、本地 MCP server compromise、scope 过宽等风险。OpenAI Codex 的 MCP 文档 支持配置 enabled/disabled tools、默认审批模式和单工具审批策略。OpenAI Codex 的 permissions 文档 也把 read-only profile、deny 规则、network allowlist 作为权限控制手段。

这些机制指向同一个做法:把策略放在工具边界,而不是寄希望于模型自觉。

一个可落地的架构

生产排障 agent 不要直接挂在生产机器上。更合适的位置,是 incident investigation control plane。

Incident / Alert
  -> context assembler
  -> policy engine
  -> observability MCP
  -> diagnostic MCP
  -> evidence store
  -> human review
  -> approved workflow or break-glass SSH
  -> postmortem artifact

这套架构需要六个平面。

平面职责关键约束
Identity planeagent 用什么身份访问系统独立身份、短期凭证、禁止共享个人 key
Policy plane决定哪些工具和数据可用按服务、环境、incident scope 授权
Data planemetrics、logs、traces、配置、拓扑字段级脱敏、限量、默认不读客户 payload
Tool planeMCP 工具和 SSH wrapper语义化工具、禁止任意 shell
Audit plane记录 prompt、工具、参数、输出能复盘每次读取和每次建议
Evaluation plane验证 agent 是否可靠历史 incident replay、红队 prompt、演练

最容易缺的是 evaluation plane。生产排障 agent 不是上线一个聊天框就结束。它需要像其他生产自动化一样被测试:

  • 用历史 incident replay,看它能不能收集到关键证据。
  • 用已知 root cause 的案例,看它是否过早下结论。
  • 在日志、工单、网页片段里注入恶意指令,验证它是否把数据当成指令。
  • 检查输出是否泄露 token、PII、内部拓扑。
  • 评估它的建议是否符合 runbook 和变更流程。
  • 记录它在 incident 中节省的时间,也记录它制造的误导。

没有 evaluation,agent 只是一个能访问生产上下文的文本生成器。

第一版做标准化取证和日志定位

第一版目标不要叫“自动排障”。先做“标准化取证和日志定位”。它要覆盖两种入口:告警或 incident 驱动的问题,以及生产日志驱动的疑难 bug。

一个可交付的 MVP 可以这样定义:

输入:alert_id、incident_id、bug_id、correlation_id、trace_id 或受控时间窗口
输出:
  1. 受影响服务、相关 SLO 或业务路径
  2. 如果没有 SLO 受损,给出请求级或业务对象级时间线
  3. 最近 30 到 60 分钟的关键指标变化
  4. 错误日志摘要,不含原始敏感字段
  5. 相似错误样本和出现频率
  6. 最近发布、配置、依赖和基础设施事件
  7. 相关 runbook
  8. 候选假设,按证据强弱排序
  9. 下一步人工检查建议
  10. 审计记录

对应的工具集合要小:

get_alert(alert_id)
get_bug_context(bug_id)
get_service_slo(service, window)
get_metric_snapshot(service, window)
get_log_schema(service)
search_sanitized_logs(service, query, window, limit)
get_request_timeline(correlation_id, window)
get_error_examples(service, signature, window, limit)
compare_log_patterns(service, baseline_window, incident_window)
get_trace_summary(service, window)
get_recent_changes(service, window)
get_runbook(service)
write_investigation_note(case_id, note)

这里允许查生产日志,但不允许随便查。查询必须绑定服务、环境、时间窗口、字段 allowlist、输出上限和 case id。优先使用 correlation id、trace id、request id、订单 id 的脱敏形式或内部业务对象 id。需要按手机号、邮箱、身份证、真实姓名这类 PII 检索时,应走更高审批等级,最好先由系统把明文字段转换成受控 token 或 hash。

第一版不应该包含:

run_shell
restart_service
rollback
kubectl
sql_query
read_file
curl
export_raw_logs

如果这一版没有价值,问题多半不在 agent。更可能是观测数据、runbook、服务拓扑和发布记录本身还没整理好。

安全红线

生产排障 agent 要有这些红线。

红线原因
正常模式不给任意生产 shellshell 是过宽接口
不给 sudosudo 直接跨过最小权限边界
不提供通用 read_file文件系统里有大量非预期敏感数据
不提供通用 kubectl(args)Kubernetes API 太大,读写边界复杂
不提供通用 sql(query)数据库查询很容易触碰客户数据
不允许无限制导出原始日志原始日志经常混有 token、PII 和业务敏感字段
不允许随意按 PII 明文检索用户标识检索要有 case 绑定、审批和脱敏
不把 MCP 裸放公网远程工具接口必须有强鉴权和网络边界
不传递用户 token 给下游工具token passthrough 会制造 confused deputy 风险
不让日志和工单成为指令它们是 untrusted input
不允许自主重启、回滚、扩容、切流量生产动作需要明确责任人
不隐藏工具调用没有审计就无法复盘

最后两条经常被低估。agent 可以给建议,但生产动作需要明确审批。agent 可以读日志,但日志里的文本不能改变工具调用策略。

分阶段落地

推荐的 rollout 路线如下。

阶段能力上线条件
Phase 0只读 runbook、postmortem、告警说明不接生产数据
Phase 1只读 incident context 和 dashboard 链接记录所有回答来源
Phase 2observability 和 log-query MCP日志脱敏、工具 allowlist、审计
Phase 3diagnostic MCP只暴露主机健康摘要,不暴露 shell
Phase 4break-glass SSH wrapper人工审批、短期凭证、输出限制
Phase 5审批式 remediation workflow演练、回滚路径、单动作审批

每个阶段都要有退出条件。Phase 2 之前,日志脱敏、字段 allowlist、查询窗口限制和输出上限必须通过测试。Phase 3 之前,诊断工具要覆盖常见 incident 和疑难 bug 的取证需求。Phase 4 之前,SSH wrapper 必须能拒绝未知命令、限制输出、记录 incident ID。Phase 5 之前,历史 incident replay 和演练要证明 workflow 不会扩大故障。

生产可靠性系统不该靠一次上线赌正确。

结论

生产排障 agent 的价值,不在于它能不能 SSH。价值在于它能否把证据收集、上下文压缩、假设生成和复盘产物做得更一致。

只读 SSH 可以作为实验入口,但不是好的默认架构。它的接口太宽,数据边界太模糊,审计语义太弱。MCP 也不是天然安全,不过它更适合承载语义化工具、审批、脱敏、限流和审计。

默认设计可以很朴素:

SLO、生产日志、trace 和观测系统作为事实入口。
MCP 作为日常诊断边界。
SSH 只做 break-glass。
生产动作必须审批。
所有工具调用必须可审计。

这不激进,但更像能在生产系统里长期运行的方案。

参考资料