关于 rustsdcmcp
rustsdcmcp 是面向管理 HPE Juniper Security Director Cloud 及其 SRX 设备群的运维人员的异步 Rust MCP 服务。它提供受限的读取和变更控制工具,变更必须经过准备、独立审批和应用。
主要功能
- 01提供 80 个 SDC 管理工具
- 02按租户和工具限定访问范围
- 03变更采用双人审批流程
- 04限制请求与响应大小
- 05审计归因时保护凭证
适用场景
- 01查看受管 SRX 设备与策略
- 02准备并审批策略变更
- 03将访问限制到指定租户和工具
MCP 相关
它通过 80 个工具向 MCP 客户端开放 HPE Juniper Security Director Cloud 的 SRX 设备与策略管理 API,涵盖读取和变更控制操作。变更须经过准备、独立审批和应用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm ghcr.io/mechubsec/rustsdcmcp:0.5.1本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/mechubsec/rustsdcmcp:0.5.1stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
rustsdcmcp
面向 HPE Juniper Security Director Cloud 的异步 Rust Model Context Protocol 服务
mechub 项目 — 主权网络安全自动化
非官方/社区项目。 这是一个独立的社区项目, 不声称与 Hewlett Packard Enterprise 或 Juniper Networks 有任何关联,也不代表其认可。 产品名称和商标仅用于标识本软件可互操作的系统。
rustsdcmcp 将 HPE Juniper Security Director Cloud(SDC)作为范围受限、可审计的工具接口开放给 MCP
客户端。SDC 是面向 SRX 设备群的 HPE Juniper SASE
门户,因此此服务连接的是该管理平面,而非任何单台防火墙。与通过
rustjunosmcp 使用 NETCONF 连接
各个 SRX 设备不同,rustsdcmcp 使用 HTTPS REST 连接管理这些设备的门户。
这一区别意味着影响范围很大:一次 SDC 操作就可能影响多台受管 SRX 设备。因此,严格审批、避免凭据泄露的操作归因以及有界 I/O,保护的是管理平面,而不只是锦上添花。
当前状态
rustsdcmcp 提供 80 个 MCP 工具(v0.4.1 和 main;v0.3.1 提供了 78 个;v0.2.0 提供了 74 个):60 个有界读取工具和 20 个变更控制工具。其覆盖范围包括 SDC API 中用于管理 SRX 设备及其策略的部分;产品 API 的其余部分明确不在范围内。
每项变更都只能通过准备 → 独立审批 → 应用的流程执行。通配符令牌范围有意不授予任何写入工具,因此创建令牌时必须逐一明确指定。
针对 SDC 的实时验证已远不止只读操作。2026-08-07,在实验室租户上执行了一次完整的 prepare → approve → apply 策略部署,并成功部署到受管 vSRX。这一过程揭示了 #23 中的共同管理行为:在 SDC 所有的层级中,无法通过 SDC 导入的策略访问到的对象会在部署时被删除。接口、路由、system 和管理实例均未受影响。完整边界和观察到的差异见 docs/operations.md。JobStatus 和 DeviceStatusEntry 已根据实时预览和部署响应进行验证。
2026-08-12,证书和许可证读取器、BulkSyncDevices 以及模板端点均经过了实时测试。设备同步是将设备导入 SDC,而不是推送到设备;不过,它只协调库存,不会清除 device_config_state: OUT_OF_BAND_CHANGED。
读取路径安全属性最近一次实时验证是在 2026-08-07,针对提交 ea81805d2b4b97df9bdd3f70423e047524896a3d 和 mecmcp v0.5.0 进行的。此后,传输和范围预检在 e28d0cc 和 369f9bb 中被替换,因此该结果已不能代表当前的 main;当时没有可用于重新进行实时验证的实验室 SDC 租户。2026-10-06,针对提交 2036523 和 mecmcp v0.26.0,重新运行了自动化集成测试套件:cargo test --workspace,258 项通过,0 项失败,覆盖以下内容:拒绝缺少 bearer 的请求(crates/rustsdcmcp/tests/http_boundary.rs::router_requires_bearer)、拒绝超出范围的租户(crates/rustsdcmcp/tests/http_boundary.rs::out_of_scope_tenant_is_refused)、精确执行工具和租户范围,并确保读写工具互斥(crates/rustsdcmcp/src/server.rs 范围单元测试、crates/rustsdcmcp/tests/tool_contract.rs),以及对响应中的密钥进行脱敏(crates/rustsdcmcp-core/src/redact.rs 单元测试)。2026-08-07 实时审计中的其余属性尚未在当前 main 上重新验证;此次测试不能替代对实时租户的测试,也不能重新确立这些属性。
已观察到的响应结构和仍待解答的端点问题记录在 docs/sdc-api/README.md 中。
下载
当前版本 v0.4.1 附带经过校验和验证并由 cosign 签名的 LXC 安装包(rustsdcmcp_0.4.1_amd64.tar.gz),作为版本资源发布。请下载并验证,或使用下文的批准源码构建。
该标签还发布了 linux/amd64 容器镜像 ghcr.io/mechubsec/rustsdcmcp:0.4.1,无需身份验证即可公开拉取。
使用批准的源码构建
rust-toolchain.toml 将构建工具链固定为 1.99.0;Cargo.toml 中声明的 MSRV 为 1.89。操作人员必须在构建、测试或打包前,将检出代码绑定到预期发布的提交;通常选择版本标签:
approved_commit=$(git rev-parse v0.4.1^{commit})
git checkout --detach "$approved_commit"
test "$(git rev-parse HEAD)" = "$approved_commit"
cargo build --release --locked
cargo test --workspace --locked
scripts/build-package.sh
cp examples/sdc.example.json /secure/operator/path/sdc.json
在此配置中,credential_env 指定外部进程变量;凭证本身绝不能放入 JSON。对于本地的提交固定版本包,请在批准的提交目录中验证新构建的归档及其中嵌入的 BUILD-INFO——切勿对 dist/ 使用通配符,因为校验和只记录归档文件的基本名称:
artifact_dir="dist/$approved_commit"
mapfile -t archives < <(find "$artifact_dir" -maxdepth 1 -type f -name 'rustsdcmcp_*_amd64.tar.gz' -print)
test "${#archives[@]}" -eq 1
archive="${archives[0]}"
(cd "$artifact_dir" && sha256sum -c "$(basename "$archive").sha256")
package_root=$(tar -tzf "$archive" | sed -n '1s#/.*##p')
test -n "$package_root"
tar -xOf "$archive" "$package_root/BUILD-INFO" | grep -Fx "git_commit=$approved_commit"
Docker 快速入门
如需运行已发布的容器镜像,请参阅 HOW-TO-SETUP-DOCKER.md。
Debian 13 LXC 快速入门
从头开始构建 LXC,请参阅 HOW-TO-SETUP-LXC.md。
先决条件:
- Debian 13 AMD64;建议使用非特权 LXC。
- 最低配置需要 1 个 vCPU、512 MiB RAM、512 MiB 交换空间和 4 GiB 磁盘。
- DNS 和时间同步正常,并可通过 HTTPS 出站访问
api.sdcloud.juniperclouds.net。 - 可在 LXC 内使用 root 或具有同等权限的运维人员账号。
下载已签名的 v0.4.1 发行版 tarball(或从经批准的源代码构建,参见上文的
从经批准的源代码构建),然后安装已验证的软件包:
set -euo pipefail
mapfile -t archives < <(find . -maxdepth 1 -type f -name 'rustsdcmcp_0.4.1_amd64.tar.gz' -print)
test "${#archives[@]}" -eq 1
archive="${archives[0]}"
sha256sum -c "$archive.sha256"
package_root=$(tar -tzf "$archive" | sed -n '1s#/.*##p')
test -n "$package_root"
tar -xzf "$archive"
sudo "$package_root/packaging/lxc/install.sh"
创建配置文件和凭据文件,且不要暴露凭据:
sudo install -o root -g rustsdcmcp -m 0640 \
/etc/rustsdcmcp/sdc.json.example /etc/rustsdcmcp/sdc.json
sudoedit /etc/rustsdcmcp/sdc.json
sudo install -o root -g root -m 0600 /dev/null \
/etc/rustsdcmcp/credentials.env
sudoedit /etc/rustsdcmcp/credentials.env
sdc.json 必须保留 HTTPS SDC 端点,使用所需的本地租户别名,并将
expected_tenant_id 设置为运维人员获取的 SDC 租户 ID。凭据文件包含一条
与 shell 兼容的赋值语句,使用 credential_env 中的名称,例如
SDC_API_TOKEN=...;切勿在 README 或 JSON 中填写真实值。
创建初始的精确 14 工具只读授权。重定向目标必须预先设置为 0600 模式;
输出是一次性持有者令牌。
sudo /usr/local/bin/rustsdcmcp token add \
--tokens-file /etc/rustsdcmcp/tokens.json \
--device-mapping /etc/rustsdcmcp/sdc.json \
--name sdc-read \
--devices production \
--tools get_sdc_tenant_scope,list_sdc_devices,get_sdc_device,list_sdc_firewall_policies,get_sdc_firewall_policy,list_sdc_nat_policies,get_sdc_nat_policy,list_sdc_resources,get_sdc_resource,get_sdc_preview_status,get_sdc_deploy_status,get_sdc_preview_device_result,get_sdc_deploy_device_result,get_sdc_change_set \
--actor-type human > /secure/local/path/rustsdcmcp-sdc-read-token
启动服务,并通过经过身份验证的 SSH 隧道访问:
sudo systemctl enable --now rustsdcmcp.service
sudo systemctl --no-pager --full status rustsdcmcp.service
sudo ss -ltnp 'sport = :30032'
ssh -N -L 30032:127.0.0.1:30032 root@your-deployment-host
预期监听地址仅为 127.0.0.1:30032。隧道启用期间,本地 MCP 客户端使用
http://127.0.0.1:30032/mcp。每个安装都使用自己的 SSH 主机;服务绝不会直接暴露。
安全承诺
- 外部凭据使用严格的文件权限,绝不放入 JSON。
- 启动时会根据
expected_tenant_id验证已配置的身份。 - 持有者令牌具有精确的工具和租户范围。
- 请求、响应和页面大小均有限制。
- 审计归属信息不会泄露凭据,目标值会经过 HMAC 脱敏。
- 变更需要由两位不同人员执行 prepare → approve → apply 变更控制。
- 不提供直接部署工具,也不存在未经身份验证的写入途径。
- 通配符令牌范围不会授予任何写入工具。
--tools '*'仅提供只读功能;创建令牌时必须明确指定每个写入工具。
详细的部署、恢复、审计保留和写入工作流指南见
docs/operations.md。
--lab-mode
--lab-mode 会免除第二位参与者的要求,适用于单人操作的实验环境,因为在这种环境中,两人控制只是走形式而非真正的控制。默认关闭,在任何重要环境中都应保持关闭。
它的作用与不会改变的事项:
- 创建变更集时会自动应用豁免。没有豁免工具,流程仍为 prepare → apply,与生产环境相同。
- 规划、计划摘要、漂移检测和应用时重新验证仍会执行。实验室模式移除的是第二位审核者,而非变更记录。
- **绝不会伪造审批者。**获得豁免的变更集会记录
approver: null和approval_waiver: "lab-mode",并携带针对(change_set_id, plan_digest, owner, approved_at)计算的豁免摘要。它在密码学上可与真正的双人审批区分开,之后也无法重新标记——如果日后有人需要证明哪些变更确实实现了职责分离,这一点至关重要。 - 启用时,服务会在启动时发出醒目警告。
如果想在不豁免控制的情况下独自测试写入功能,请创建两个名称不同的令牌,一个用于 prepare,另一个用于 approve:令牌名称就是参与者身份,系统会拒绝自我审批。这样一来,一人即可完成整个生命周期,同时保留控制措施;只要这套流程具有任何价值,这就是更好的选择。
启用
将标志添加到服务单元。通过软件包安装时,请使用 drop-in 文件,而不是编辑随软件包提供的单元文件,这样升级时就不会悄然丢失该设置:
sudo systemctl edit rustsdcmcp
替换 ExecStart 意味着必须完整重写它,因此请复制随软件包提供的命令并追加标志,不要写一个更短的命令。删掉 --audit-* 参数会在启用实验模式时,连带关闭 HMAC 目标脱敏和结构化 journald 审计:
[Service]
# Clear the shipped ExecStart before replacing it; systemd appends otherwise.
ExecStart=
ExecStart=/usr/local/bin/rustsdcmcp \
--device-mapping /etc/rustsdcmcp/sdc.json \
--transport streamable-http \
--host 127.0.0.1 \
--port 30032 \
--tokens-file /etc/rustsdcmcp/tokens.json \
--audit-format json \
--audit-journald \
--audit-redact devices=hmac \
--audit-hmac-key-file /etc/rustsdcmcp/audit-hmac.key \
--lab-mode
应用前,请对照 packaging/systemd/rustsdcmcp.service 检查——随软件包提供的参数是权威依据,而此代码片段只是副本,可能已经过时。
sudo systemctl daemon-reload && sudo systemctl restart rustsdcmcp
确认设置已生效。两条启动记录使用了不同的拼写——警告中是 --lab-mode,解析后的配置行中是 lab_mode——因此请同时匹配两者,并以足够的权限读取日志,才能查看系统单元:
sudo journalctl -u rustsdcmcp -b | grep -E 'lab.mode'
{"level":"WARN","fields":{"message":"--lab-mode: two-person control is DISABLED. …"}}
{"level":"INFO","fields":{"message":"change-control configuration resolved","lab_mode":true,…}}
没有输出表示该功能未启用。由于权限不足,非特权用户运行 journalctl 时也可能没有任何输出,并不代表该标志未设置,因此命令使用了 sudo。
被豁免的变更集会由 prepare_sdc_policy_deploy 直接报告 "state": "approved"、"approver": null 和 "approval_waiver": "lab-mode",而 apply_sdc_change_set 无需单独调用审批。
若要临时运行而非作为服务运行,也可以用相同方式在命令行中传入 --lab-mode。
优先级
--lab-mode 属于 mecmcp 共享的变更集 CLI 标准,与 --state-file 和 --approval-timeout-secs 并列。对于另外两个标志,显式传入的值优先;否则,sdc.json 会提供相应的值(changeset_state_file、approval_ttl_secs)。
--lab-mode 仅限 CLI 使用。 有意不提供对应的 sdc.json 字段:宽松的安全控制应当要求操作员在自己看得到的单元文件中手动输入,而不应从数月前编辑的配置文件继承。共享标准是否允许回退到产品配置仍是一个尚未解决的上游问题(mecmcp#267);此服务采用保守的解释。
部署成熟度
Debian 13 软件包已通过 CI 构建的、对应提交 ea81805d2b4b97df9bdd3f70423e047524896a3d 的归档完成端到端安装和运行。它以非 root 账户在随软件包提供的 rustsdcmcp.service 单元下启动,绑定仅限回环的端点,执行 bearer 边界检查,并通过对实时 SDC 的启动租户范围检查。
有一项软件包限制值得明确说明:只有当主机允许 systemd 附加其 cgroup BPF 程序时,单元中的 IPAddressAllow 和 IPAddressDeny 行才会生效;这取决于运行环境。在经过验证的部署中,安装程序探测结果为 NOT ENFORCED,因此必须在单元之外强制执行出口流量限制;其他所有沙箱指令仍然生效。请根据自己主机上的探测结果操作,不要想当然地认为设置一定生效或一定无效。部署、恢复、审计保留以及各运行环境对应的出口流量限制机制,请参阅 docs/operations.md。
此处有意不公开具体主机、地址和容器标识符;每位操作员都应提供自己的信息。
路线图
请参阅 ROADMAP.md,了解当前覆盖范围、计划扩展内容以及受上游 API 支持限制的功能。欢迎通过 GitHub issue 提交功能请求。
与 mecmcp 的关系
mecmcp 是 mechub MCP 服务系列共享的供应商中立 Rust 基础。本仓库使用它,而非从其分叉。main 将全部八个共享 crate 固定到 v0.27.0:mecmcp-audit、mecmcp-auth、mecmcp-changeset、mecmcp-redact、mecmcp-runtime、mecmcp-secret、mecmcp-server 和 mecmcp-transport。
兼容性阻碍已解除。 本节的早期版本曾指出,在用一个统一的上游版本取代 59 项临时兼容性声明之前,发布会受阻。此事已经完成:迁移到 mecmcp 0.7.2 时,#36 删除了本地 compat/ 层;迁移到 0.8.0 时,369f9bb 又移除了兼容性台账。现在已没有临时兼容性符号,也没有需要跟踪的台账。
API 来源
API 表面固定依据 Juniper 导出的 OpenAPI 3 规范,该规范随仓库存放在 docs/sdc-api/ 中。它是受支持的 SDC API 表面的权威清单,也记录了尚待解决的问题。
主要参考资料:
将审计记录转发到事件存储
审计跟踪不会留在此主机上。本服务遵循系列标准——AUDIT-FORWARDING-STANDARD.md。
如果审计记录只存在于生成它的机器上,那就不算审计跟踪:它只是存放在一台机器上的日志文件,而这台机器的操作者正是记录所涉及的对象。
发出记录(当前已生效)
--audit-format json \
--audit-log-file /var/lib/rustsdcmcp/audit.jsonl
必须使用 JSON。text 格式供在终端中阅读,不可作为解析目标。文件是面向操作者的产物,必须轮转——服务端绝不会截断它。
传输
根据 SSDF 的合并证据约定,记录会直接写入 SSDF 的 ssdf.audit,作为哈希链式行,以便检测行是否被删除或编辑。此功能已实现:配置证据转发时,服务端会在启动时连接一对 EvidenceService/EvidenceHttpTransport(crates/rustsdcmcp/src/main.rs),该功能作为 SSDF 证据管道在 mecmcp#292 中合并。
我们曾设计一条成本更低的 syslog 路径,但最终否决了:它虽然可行,但记录没有链式保护;而此处其他每个环节在设计上都具备防篡改能力——计划摘要会绑定审批,审批会指明唯一主体,而 token_verified_fields 会区分经背书的来源信息与声明信息。最后一跳如果没有链式保护,就会在审计人员最需要这一保证的地方将其丢弃。相关理由已记录在标准中。
查看结果
token_verified_fields 指明了经 token 背书的来源字段。该字段组中的其余字段——client_name、model_id、session_id——由客户端声明,不受任何认证。不要将它们视为等同。
request_id 用于关联传输事件、处理程序事件,以及(在 Junos 上)设备提交注释。
许可证
根据 MIT 许可。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。