Skip to content

账号、门户与自动对等

身份与自动对等子系统。主体是 L1 配置事实源分层模型)——账号、会话、审计与策略都需要事务、关联查询与审计追溯,丢了不可重建;另有一张 L3 时序表(autopeer_route_rollup)与一张已退为降级路径的表(portal_login_transactions)。

控制库中存在两个完全分离的信任域,本册各覆盖其一:

信任域主体覆盖的接口
管理员运维人员admin_usersadmin_sessionsadmin_audit_log/control/v1/admin/* 全部写操作
门户用户外部 AS 的维护者portal_login_transactionsportal_sessionspeering_requests/control/v1/autopeering/*,权限按已验证 ASN 划分

autopeering_node_policies 位于两域交界:由管理员写入(开放哪些节点、开放何种能力),供门户用户读取。

一处例外:登录往返的瞬态凭据(portal_login_transactions)主路径已迁至 L4(Valkey),本表退为降级路径,详见下文。


admin_users

一个管理员账号。app/db/models/auth.py

类型约束 / 默认说明
idIntegerPK,autoincrement主键
usernameString(64)NOT NULL,unique用户名
password_hashString(255)NOT NULLargon2id 编码串(含参数与盐,形如 $argon2id$v=19$m=…
roleString(32)NOT NULL,默认 admin预留字段,当前恒为 admin,无权限分级
created_at / updated_atDateTime(tz)NOT NULL,server_default now,updated_at 带 onupdate时间戳

admin_sessions

账号登录签发的一条会话。

类型约束 / 默认说明
idIntegerPK,autoincrement主键
user_idIntegerFK→admin_users.id(CASCADE),NOT NULL,index所属账号
token_hashString(64)NOT NULL,unique完整 Bearer 的 sha256 十六进制摘要(唯一查找键)
created_atDateTime(tz)NOT NULL,server_default now签发时刻
expires_atDateTime(tz)NOT NULL过期时刻
revoked_atDateTime(tz)可空非空即已吊销(改密时批量吊销该用户全部会话)

安全模型与 agent token 同纪律:明文令牌永不落库,只存 sha256 摘要;密码只存 argon2id 单向散列。账号会话令牌与静态 DN42_CONTROL_ADMIN_TOKENrequire_admin 同一入口无差别接受。登录失败计数在 L4(throttle:login:*),不落库。


admin_audit_log

append-only 的管理写操作记录。app/db/models/audit.py。无外键。每条对应一次到达 /control/v1/admin 的变更类请求(POST / PUT / PATCH / DELETE),无论鉴权是否通过

类型约束 / 默认说明
idIntegerPK,autoincrement主键
actorString(64)可空,index鉴权通过的主体:静态 admin token 记 admin,账号会话记用户名;鉴权失败时为空
methodString(8)NOT NULLHTTP 方法
pathString(512)NOT NULL,index请求路径
status_codeIntegerNOT NULL响应状态码
detailJSONNOT NULL,默认 {}详情(如 query 串)
created_atDateTime(tz)server_default now,index写入时刻

不设保留期:审计是唯一一张有意无限增长的表。当前 883 行 / 272 kB,按现有写入频率(管理写操作本身稀疏)无需处置。


portal_login_transactions

降级路径专用——主路径在 L4(Valkey db 1 的 portal:login:<state>,TTL 30 分钟)。

一次进行中的 OIDC 授权往返,短 TTL、单次使用。app/db/models/portal.py

登录事务属于「30 分钟内消费一次即作废、无审计价值、不参与关联查询」的瞬态凭据,置于 KV 优于 PostgreSQL:TTL 自动回收、GETDEL 原子消费,同时免去一张表的死元组与「条件 UPDATE 抢占消费」的实现。KV 未配置或写入失败时自动落回本表,切换期间已在途的登录仍可正常完成(services/portal_sessions.py 保留两条路径)。

会话本身(portal_sessions留在 L1:它有吊销语义、要被审计、还挂着上游 token 的刷新状态。

类型约束 / 默认说明
stateString(64)PK授权请求的 state,也是回调查找键
nonceString(64)NOT NULLID Token 绑定用 nonce
code_verifierString(128)NOT NULLPKCE 私密串,只在服务端
return_pathString(512)NOT NULL,默认 /登录后回跳的站内相对路径(防开放重定向)
expires_atDateTime(tz)NOT NULL30 分钟窗口
used_atDateTime(tz)可空非空即已消耗(条件 UPDATE 保证单次使用)
created_atDateTime(tz)server_default now时间戳

portal_sessions

门户自有登录会话,与上游令牌解耦(TTL 见 [portal] session_ttl_seconds)。会话令牌只存 sha256。

注意:上游 access token 与 refresh token 以明文存储,因为服务端需要再次使用它们。这是控制库中敏感度最高的两张表之一,备份与访问控制应按此定级(另一张为 node_wireguard_keys)。

类型约束 / 默认说明
token_hashString(64)PK会话令牌 sha256;兑换交接码时轮换
subString(64)NOT NULL,indexOIDC 稳定标识(维护者 × AS)
asnBigIntegerNOT NULL,index已验证的 ASN,门户端点按它划权
mntnerString(128)可空活跃维护者
claimsJSONNOT NULL,默认 {}最近一次 ID Token / userinfo claims 缓存
claims_refreshed_atDateTime(tz)可空claims 刷新时刻
oidc_access_token / oidc_refresh_tokenText可空上游令牌(明文,见上)
oidc_access_expires_atDateTime(tz)可空上游 access token 过期时刻
handoff_hashString(64)可空,index一次性交接码 sha256;兑换后置空
handoff_expires_atDateTime(tz)可空交接码 2 分钟窗口
expires_at / revoked_at / created_atDateTime(tz)会话生命周期

autopeering_node_policies

节点的自动对等供给策略。app/db/models/autopeering.py

类型约束 / 默认说明
node_idString(64)PK,FK→nodes.node_id(CASCADE)节点
enabledBooleanNOT NULL,默认 false是否开放自动对等
endpoint_hostString(255)可空对端拨入用的公网主机名或 IP(不含端口)。未配置表示只支持本网主动拨出的形态,该节点不出现在可拨入清单里
max_sessionsInteger可空可选的额外会话上限。可用连接数的单一事实源是外部端口池剩余量;本列为 NULL 表示只受端口池约束
notesString(512)可空运维备注
regionString(32)可空大区枚举:east-asia / southeast-asia / europe / north-america / pacific-oceania / other。前端分类标签的口径,服务端不参与过滤
country_codeString(2)可空ISO 3166-1 alpha-2,前端渲染国旗
descriptionString(256)可空一句话卖点
bandwidth_mbpsInteger可空标称带宽(仅展示)
monthly_quota_gbInteger可空月流量配额(仅展示用量占比,超额不触发任何处置)
noticeString(256)可空告警条文案;有值前端渲染提示
created_at / updated_atDateTime(tz)server_default now时间戳

peering_requests

一条自动对等请求。

提交即落成:同事务建 Peering 聚合并 materialize,status 直接落 provisioneddecided_by='auto'。免审批的依据是身份已由门户会话背书(ASN 归属验证),且配额与容量全部机器可判。请求或当场落成,或整体回滚且不留残行。

pendingrejected 是审批闸门时期的遗留状态值,当前代码不产出;cancelled 是拆除终态(用户自助拆除,或运维删聚合时联动推进)。手工建立的外部对等在对应 ASN 拉取门户列表时惰性收养为请求行(decided_by='adopted')。

连接参数列是提交或收养时刻的审计快照——落成后的展示真相在 Peering 聚合的接口与 BGP spec 里,门户读路径现查派生,管理面改动聚合后展示自动跟进,本表列不回写。

类型约束 / 默认说明
idIntegerPK,autoincrement请求 ID
asnBigIntegerNOT NULL,index请求方 ASN(取自门户会话,已验证)
subString(64)NOT NULL请求方稳定标识快照
mntnerString(128)可空请求方维护者快照
node_idString(64)FK→nodes.node_id(CASCADE),NOT NULL,index目标节点
statusString(16)NOT NULL,默认 pending,index状态机存储态
wg_public_keyString(64)可空对端 WG 公钥快照。表单只收公钥,绝不收私钥
remote_endpointString(255)可空对端拨入口 host:port 快照;空表示对端不提供固定入口
remote_link_localString(64)可空对端隧道 link-local 快照
notesString(512)可空用户留言
session_addressingString(16)NOT NULL,默认 link-locallink-local / ipv6-ula,仅 mp_bgp=true 时有意义
mp_bgpBooleanNOT NULL,默认 truefalse 表示 v4 + v6 双纯会话
peer_ipv4 / peer_ipv6String(64)可空对端隧道内地址(经 registry route / route6 校验)
peering_idIntegerFK→peerings.id(SET NULL),可空落成的 Peering
interface_name / listen_port / mtuString(64) / Integer / Integer可空落成结果快照
probed_pmtuInteger可空二分扫出的路径 MTU(接口 MTU 口径)。探测不改 spec,mismatch 只提示
mtu_probe_statusString(16)可空ok / mismatch / unreachable;三列全空表示未探测
mtu_probed_atDateTime(tz)可空MTU 探测时刻
latency_rtt_avg_ms / latency_rtt_max_ms / latency_loss_pctFloat可空RTT 与丢包采样结果
latency_probed_atDateTime(tz)可空延迟探测时刻
decided_by / decided_at / reject_reasonString / DateTime(tz) / String可空决策轨迹
created_at / updated_atDateTime(tz)server_default now时间戳

部分唯一索引 UNIQUE(asn, node_id) WHERE status IN ('pending','provisioned')——同一个 AS 对同一节点最多一条在途或生效的对等,从 DB 层兜住并发提交竞态。


autopeer_route_rollup

自动对等会话的路由计数时序(每 节点 × 接口 × 5 min 桶,L3),是门户状态页时序图的数据层。app/db/models/autopeering.py

数据源:runtime snapshot 入库时对该节点的 autopeer 接口按 node_route_entries 计数(导入侧),upsert 当前桶。导出侧列在 agent 上报 per-AF 计数(1.0.233+)就位后由快照直读填充,更早的 agent 期间恒空。

注意:本表为 gauge 语义——取该桶最后一次观测值,既不累加也不求平均。这是全库唯一不设 sum / count 的时序表:路由条数属于瞬时量,累加同一桶内的多次观测没有意义。通用桶形态见时序建模通则

类型约束 / 默认说明
node_idString(64)PK(复合),FK→nodes.node_id(CASCADE)所属节点
interfaceString(64)PK(复合)接口名
bucket_startBigIntegerPK(复合)桶起点(epoch 秒,对齐 5 min)
imported_v4 / imported_v6IntegerNOT NULL,默认 0导入路由计数
exported_v4 / exported_v6Integer可空导出路由计数;旧 agent 期间为 NULL
updated_atDateTime(tz)server_default now,带 onupdate更新时刻

保留 60 天,与流量存档同口径。