外观
API 参考
本目录是三个后端服务全部 HTTP / WebSocket 接口的单一事实源。每个端点的方法、路径、请求体、响应体、鉴权与状态码均取自源码,不收录未实现的接口。
服务与基址
| 服务 | 代码 | 对外基址 | 业务前缀 | 可达性 |
|---|---|---|---|---|
| Control Server | apps/control-server | https://api.natlan.io | /control/v1/* | 公网 |
| Auth Server | apps/auth-server | https://auth.natlan.io | /api/v1/*(OIDC 协议端点挂在根上) | 公网 |
| Registry Server | apps/registry-server | 无 | /registry/v1/* | 仅容器网内 |
前缀由应用自身挂载,前置 nginx 只按路径转发、不做 rewrite。因此 /docs、OpenAPI 文档里的路径以及 FastAPI 尾斜杠 307 的 Location 都是真实对外路径。反过来做(nginx 剥前缀 + 应用挂 /v1)会让这两处静默出错。
auth-server 独占一个主机名,主机名本身已完成服务分段,故其业务前缀保持 /api/v1,不再叠加 /auth。
分册
| 文档 | 内容 |
|---|---|
| 管理面 API | Control Server 管理面 /control/v1/admin/*:节点、Peering、接口、BGP、DNS、token、审批、provision、健康、路由、审计、agent 发布、flap 处置、fleet 收权 |
| 控制台 BFF API | Control Server 控制台 BFF /control/v1/ui/*:聚合视图、趋势、榜单、registry 代理、拨测与日志 |
| 自动对等 API | Control Server 用户面 /control/v1/autopeering/*:门户登录闭环、对等请求、只读网络态势 |
| 节点面 API | Control Server 节点面 /control/v1/agent/*:注册、拉取期望状态、上报、自更新分发、三条 WebSocket 通道 |
| 公开 API | Control Server 公开只读 /control/v1/public/* 与健康探针 |
| 认证服务 API | Auth Server 全部端点:ASN 归属验证、Passkey、OAuth 2.0 / OIDC Provider、运维面 |
| Registry 服务 API | Registry Server 全部端点:DN42 registry 副本查询与同步 |
鉴权模型
装配点:apps/control-server/app/api/deps.py。控制面共有四种互不相通的凭据。
| 凭据 | 作用域 | 依赖 | 取得方式 |
|---|---|---|---|
| Admin Bearer | /control/v1/admin/*、/control/v1/ui/* | require_admin | 静态 admin token(DN42_CONTROL_ADMIN_TOKEN,机器与自动化用)或账号登录签发的会话令牌 |
| Agent Bearer | /control/v1/agent/*(/register 除外) | require_agent | 节点注册时签发,绑定单个 node_id |
| 门户会话令牌 | /control/v1/autopeering/* 绝大多数端点 | require_portal_session | 门户 OIDC 登录闭环签发,按会话内 ASN 划权 |
| 会话 JWT | /control/v1/autopeering/session | require_peering_session | auth-server 的 ASN 归属验证流签发,控制面经 JWKS 本地无状态验签 |
规则细节:
- Admin:两种凭据在
require_admin单入口无差别接受,返回值即审计 actor(静态 token 记admin,账号会话记用户名)。未配置 admin token 时整个管理面 fail-closed,一律403(账号登录同样锁定);Bearer 缺失、错误、会话过期或被吊销返回401。 - Agent:token 绑定单个节点,请求体里的
node_id与绑定节点不一致返回403;token 解析失败401。 - 注册端点(
POST /control/v1/agent/register)不带 Bearer,enrollment token 在请求体里携带。 - 门户会话与管理员会话是完全分开的信任域:门户令牌只解锁
/autopeering/*,打不进 Admin API。
token 形态
| token | 形态 | 存储 | 可见窗口 |
|---|---|---|---|
| Agent token | <token_id>.<secret>,token_id 形如 agt_xxxxxx | 仅 SHA-256 哈希 | 签发 / 轮换响应中出现一次 |
| Enrollment token | 同上,token_id 形如 ent_xxxxxx | 仅 SHA-256 哈希 | 创建响应中出现一次 |
| 全局 bootstrap enrollment token | 配置项 DN42_CONTROL_ENROLLMENT_TOKEN | 仅内存 | 不绑定节点、可重复使用;未配置即关闭 |
| 账号会话令牌 | 32 字节熵的不透明随机串 | 仅 SHA-256 哈希 | 登录响应;TTL 默认 24h,改密即全量吊销 |
| 门户会话令牌 | 不透明随机串 | 仅哈希 | 交接码兑换响应;TTL 默认 120 天 |
Agent token 与 enrollment token 均可设过期(expires_at),过期后解析返回 401。完整安全模型见 安全模型。
通用约定
错误状态码
| 码 | 语义 |
|---|---|
400 | 引用了不存在的关联资源(如 peering 的 remote_node_id),或人机验证失败 |
403 | 鉴权通过但无权访问该资源;或管理面 fail-closed |
404 | 路径上的资源不存在;也用于防枚举(他人的资源一律视同不存在) |
409 | 唯一约束冲突(重名、已存在),或语义冲突(活节点直删、WG 端口占用、notify 时无在线 agent) |
422 | schema 校验失败,响应体形如 {"detail": {"message": "...", "errors": [...]}} |
429 | 触发限速(登录、挑战、拨测并发) |
503 | 依赖未配置或不可达时的 fail-closed(registry 副本、auth-server、门户 OIDC 凭据) |
错误 detail 文案是稳定接口。 前端按字面展示或匹配,改动视为破坏性变更。
审计:全部 /control/v1/admin/* 的写请求(POST / PUT / PATCH / DELETE)由 audit_admin_writes 中间件记入审计日志。中间件包在鉴权外层,鉴权失败的尝试也会留痕。
OpenAPI:三个服务各自挂 /docs(Swagger UI)与 /openapi.json。控制面的 Swagger UI 默认全折叠、开顶部过滤框、隐藏底部模型区(端点逾百,装配见 app/main.py 的 swagger_ui_parameters)。
趋势类参数:控制台侧的时间序列端点共享 range / compare 语义——range ∈ 6h / 24h / 7d / 30d,序列为定长分桶网格(点数 ≤200,空桶留 null);compare=1 附带紧邻上一窗口的对比序列(同粒度同桶数,按索引对齐)。
相关文档
配置参考 · DesiredState 字段 · 数据库 schema · 安全模型