# RTR Admin API 本文档描述 RTR server 当前提供的 HTTP 管理接口。 ## 启用方式 Admin API 默认关闭。设置 `RPKI_RTR_ADMIN_ADDR` 后启用: ```env RPKI_RTR_ADMIN_ADDR=127.0.0.1:8323 RPKI_RTR_ADMIN_TOKEN=change-me ``` 如果在 Docker 中需要从宿主机访问,容器内建议监听: ```env RPKI_RTR_ADMIN_ADDR=0.0.0.0:8323 RPKI_RTR_ADMIN_TOKEN=change-me ``` 并在 compose 中映射端口: ```yaml ports: - "8323:8323" ``` 安全规则: - `RPKI_RTR_ADMIN_ADDR` 为空时,不启动 Admin API。 - 非 loopback 地址,例如 `0.0.0.0:8323`,必须配置 `RPKI_RTR_ADMIN_TOKEN`,否则 admin server 会拒绝启动。 - 设置 token 后,请求必须带 `Authorization: Bearer `。 ## 通用 Headers ```http Authorization: Bearer change-me Content-Type: application/json ``` GET 请求不需要 `Content-Type`。 ## GET /admin/rtr/health 用于检查 Admin API 是否可达,以及当前启用了哪些管理能力。 ```bash curl http://127.0.0.1:8323/admin/rtr/health \ -H "Authorization: Bearer change-me" ``` 响应示例: ```json { "status": "ok", "config_api": true, "source_reload_api": true, "slurm_api": true, "logs_api": true } ``` ## GET /admin/rtr/logs/tail 实时读取 RTR 服务日志,效果类似 `tail -f`。默认读取 stdout 日志,先返回最近 200 行,然后持续输出新增内容。 ```bash curl -N "http://127.0.0.1:8323/admin/rtr/logs/tail?stream=stdout&lines=200&follow=true" \ -H "Authorization: Bearer change-me" ``` Query 参数: | 参数 | 默认值 | 说明 | | --- | --- | --- | | `stream` | `stdout` | 可选 `stdout` 或 `stderr`。 | | `lines` | `200` | 首次返回的历史行数,范围会限制在 `1..=5000`。 | | `follow` | `true` | `true` 时保持连接并持续输出新增日志;`false` 时只返回当前 tail 内容。 | 日志文件路径按容器 entrypoint 的规则解析: - 目录:`RPKI_RTR_LOG_DIR`,默认 `/app/logs`。 - 文件名前缀:`RPKI_RTR_LOG_NAME`,未设置时使用 `HOSTNAME`,再未设置时为 `rpki-rtr`。 - stdout 文件:`.stdout.log`。 - stderr 文件:`.stderr.log`。 ## GET /admin/rtr/config 查询当前运行中的 runtime 配置。 ```bash curl http://127.0.0.1:8323/admin/rtr/config \ -H "Authorization: Bearer change-me" ``` 响应示例: ```json { "status": "ok", "config": { "max_delta": 10, "prune_delta_by_snapshot_size": true, "source_refresh_interval_seconds": 300, "runtime_report_interval_seconds": 300, "report_history_limit": 10, "strict_ccr_validation": false, "timezone": "Asia/Shanghai", "timing": { "refresh": 3600, "retry": 600, "expire": 7200 } } } ``` ## POST /admin/rtr/config 运行中动态修改 RTR server 的部分 runtime 配置。请求体是 JSON object,支持部分更新,只需要传要修改的字段。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `max_delta` | integer | 每个 RTR 版本最多保留的 delta 条数,必须 `>= 1`。 | | `prune_delta_by_snapshot_size` | boolean | 是否按 snapshot wire size 裁剪 delta window。 | | `source_refresh_interval_seconds` | integer | CCR/SLURM source refresh 间隔,单位秒,必须 `>= 1`。 | | `runtime_report_interval_seconds` | integer | `rtr-runtime-*.json` 周期写入间隔,单位秒,必须 `>= 1`。 | | `report_history_limit` | integer | 每类 report 文件滚动保留数量,必须 `>= 1`。 | | `strict_ccr_validation` | boolean | 是否严格校验 CCR 中的非法 VRP/VAP,影响下一次 source refresh。 | | `timezone` | string | IANA 时区名,例如 `Asia/Shanghai`、`UTC`、`Europe/London`。 | | `timing.refresh` | integer | RTR EndOfData `refresh`,单位秒。 | | `timing.retry` | integer | RTR EndOfData `retry`,单位秒。 | | `timing.expire` | integer | RTR EndOfData `expire`,必须大于 `refresh` 和 `retry`。 | 示例: ```bash curl -X POST http://127.0.0.1:8323/admin/rtr/config \ -H "Content-Type: application/json" \ -H "Authorization: Bearer change-me" \ -d '{"max_delta": 6}' ``` 成功响应: ```json { "status": "ok", "config": { "max_delta": 6, "prune_delta_by_snapshot_size": true, "source_refresh_interval_seconds": 300, "runtime_report_interval_seconds": 300, "report_history_limit": 10, "strict_ccr_validation": false, "timezone": "Asia/Shanghai", "timing": { "refresh": 3600, "retry": 600, "expire": 7200 } } } ``` ## GET /admin/rtr/slurm/files 列出 `RPKI_RTR_SLURM_DIR` 下的 SLURM 文件。只返回合法的 `*.slurm` 和 `*.slurm.disabled` 文件,不返回 `.backup/`。 ```bash curl http://127.0.0.1:8323/admin/rtr/slurm/files \ -H "Authorization: Bearer change-me" ``` 响应示例: ```json { "status": "ok", "files": [ { "name": "local-policy.slurm", "path": "/app/slurm/local-policy.slurm", "enabled": true, "size_bytes": 168, "modified_unix_seconds": 1782100000 }, { "name": "old-policy.slurm.disabled", "path": "/app/slurm/old-policy.slurm.disabled", "enabled": false, "size_bytes": 168, "modified_unix_seconds": 1782100100 } ] } ``` ## GET /admin/rtr/slurm/files/{name} 读取单个 SLURM 文件,前端编辑页面可以直接使用这个接口加载内容。 ```bash curl http://127.0.0.1:8323/admin/rtr/slurm/files/local-policy.slurm \ -H "Authorization: Bearer change-me" ``` 响应示例: ```json { "status": "ok", "file": { "name": "local-policy.slurm", "path": "/app/slurm/local-policy.slurm", "enabled": true, "size_bytes": 168, "modified_unix_seconds": 1782100000, "content": "{ \"slurmVersion\": 1, \"validationOutputFilters\": { \"prefixFilters\": [], \"bgpsecFilters\": [] }, \"locallyAddedAssertions\": { \"prefixAssertions\": [], \"bgpsecAssertions\": [] } }" } } ``` ## POST /admin/rtr/slurm/files 新增或覆盖一个 SLURM 文件。文件名放在请求体中。 ```json { "name": "local-policy.slurm", "content": "{ \"slurmVersion\": 1, \"validationOutputFilters\": { \"prefixFilters\": [], \"bgpsecFilters\": [] }, \"locallyAddedAssertions\": { \"prefixAssertions\": [], \"bgpsecAssertions\": [] } }", "reload": true } ``` ## PUT /admin/rtr/slurm/files/{name} 新增或覆盖指定 SLURM 文件。 ```bash curl -X PUT http://127.0.0.1:8323/admin/rtr/slurm/files/local-policy.slurm \ -H "Content-Type: application/json" \ -H "Authorization: Bearer change-me" \ -d '{ "content": "{ \"slurmVersion\": 1, \"validationOutputFilters\": { \"prefixFilters\": [], \"bgpsecFilters\": [] }, \"locallyAddedAssertions\": { \"prefixAssertions\": [], \"bgpsecAssertions\": [] } }", "reload": true }' ``` ## DELETE /admin/rtr/slurm/files/{name} 删除指定 SLURM 文件。删除前会先备份。 ```bash curl -X DELETE "http://127.0.0.1:8323/admin/rtr/slurm/files/local-policy.slurm?reload=true" \ -H "Authorization: Bearer change-me" ``` ## POST /admin/rtr/slurm/files/{name}/disable 将启用文件改名为失效文件: ```text local-policy.slurm -> local-policy.slurm.disabled ``` ```bash curl -X POST "http://127.0.0.1:8323/admin/rtr/slurm/files/local-policy.slurm/disable?reload=true" \ -H "Authorization: Bearer change-me" ``` ## POST /admin/rtr/slurm/files/{name}/enable 将失效文件改名为启用文件: ```text local-policy.slurm.disabled -> local-policy.slurm ``` ```bash curl -X POST "http://127.0.0.1:8323/admin/rtr/slurm/files/local-policy.slurm.disabled/enable?reload=true" \ -H "Authorization: Bearer change-me" ``` ## POST /admin/rtr/slurm/reload 不修改文件,只立即触发一次 CCR/SLURM source reload。 ```bash curl -X POST http://127.0.0.1:8323/admin/rtr/slurm/reload \ -H "Authorization: Bearer change-me" ``` ## SLURM 文件规则 - `*.slurm`:启用,会被 source refresh 加载。 - `*.slurm.disabled`:失效,不会被加载。 - `.backup/`:接口自动生成的备份目录。 - 文件名只能是 basename,不能包含 `/`、`\` 或 `..`。 - 文件名只能包含 ASCII 字母、数字、`.`、`_`、`-`。 - 写入内容必须是合法 JSON,并且能被解析为合法 SLURM 文件。 - 单个请求体默认限制为 5 MiB。 - 覆盖、删除前会写入 `.backup/` 备份。 ## 错误响应 | HTTP 状态码 | 含义 | | --- | --- | | `400 Bad Request` | JSON 非法、配置值非法、SLURM 文件名非法、目标文件不存在、reload 失败等。 | | `401 Unauthorized` | 配置了 token,但请求缺少或使用了错误的 `Authorization`。 | | `404 Not Found` | 路径或方法不支持。 | | `413 Payload Too Large` | 请求体超过限制。 |