认证
OpenViking Server 支持三种内置认证模式,并带有基于角色的访问控制:api_key、trusted 和 dev。如果未显式配置,模式会自动推导。此外,系统支持自定义认证插件,可对接任意身份源(如 LDAP、OIDC、mTLS 等)。
概述
OpenViking 使用两层 API Key 体系:
| Key 类型 | 创建方式 | 角色 | 用途 |
|---|---|---|---|
| Root Key | 服务端配置(root_api_key) | ROOT | 账户管理 + 少量 system/monitoring 操作 |
| User Key | Admin API | ADMIN 或 USER | 租户内数据访问;ADMIN 还可管理本 account 下的用户 |
User key 由 Admin API 生成。默认使用随机 secret;Admin API 调用方也可以传入 seed,用 sha256(user_id + "\0" + seed) 生成可预测的 key secret。服务端仍然 会用存储的 key 或 key hash 校验最终 API Key。
认证模式
| 模式 | server.auth_mode | 身份来源 | 典型使用场景 |
|---|---|---|---|
| API Key 模式 | "api_key" | API Key;数据归属从 user/admin key 解析 | 标准多租户部署 |
| Trusted 模式 | "trusted" | X-OpenViking-Account / X-OpenViking-User;非 localhost 部署还必须配置 root_api_key。角色会从 APIKeyManager 查询(如果用户存在) | 部署在受信网关或内网边界之后 |
| Dev 模式 | "dev" | 无认证,始终为 ROOT | 仅限本地开发 |
如果未显式配置 auth_mode:
- 如果设置了
root_api_key(非空):自动选择api_key模式 - 如果未设置
root_api_key:自动选择dev模式
注意: 将
root_api_key设置为空字符串""是非法的。请要么设置一个非空值,要么完全移除该配置项。
服务端配置
在 ov.conf 的 server 段配置认证模式:
{
"server": {
"auth_mode": "api_key",
"root_api_key": "your-secret-root-key"
}
}启动服务:
openviking-server自定义认证插件
服务端采用插件化认证架构。每种 auth_mode 对应一个 AuthPlugin 实现。内置插件(dev、api_key、trusted)会自动注册;第三方插件可通过继承 AuthPlugin 并在启动前注册来扩展。
插件接口(openviking.server.auth.plugin.AuthPlugin)
| 方法 | 用途 |
|---|---|
resolve_identity(request, api_key, x_openviking_account, x_openviking_user) | 将凭据解析为 ResolvedIdentity。 |
validate_config(config) | 在启动时校验 ServerConfig;遇到致命错误应调用 sys.exit(1)。 |
initialize(app, service, config) | 在 app.state 上初始化运行时状态(如 APIKeyManager)。 |
get_request_context_checks(path, identity) | 可选的认证后路径/身份检查。 |
requires_api_key_manager() | Admin API 路由是否需要 APIKeyManager。 |
can_skip_api_key_for_bot_proxy() | Bot 代理是否可以跳过 API Key 校验(如 dev 模式)。 |
注册自定义插件
from openviking.server.auth.plugin import AuthPlugin
from openviking.server.auth.registry import register_auth_plugin
from openviking.server.identity import ResolvedIdentity, Role
@register_auth_plugin
class LDAPAuthPlugin(AuthPlugin):
auth_mode = "ldap"
async def resolve_identity(self, request, *, api_key=None, x_openviking_account=None, x_openviking_user=None):
# ... LDAP 绑定与身份解析 ...
return ResolvedIdentity(role=Role.USER, account_id="...", user_id="...")
def validate_config(self, config):
pass
async def initialize(self, app, service, config):
pass然后在 ov.conf 中设置 server.auth_mode = "ldap"。
自定义角色
内置的 Role 类支持动态注册自定义角色及权限等级:
from openviking.server.identity import Role
Role.register("operator", rank=1) # 权限介于 USER (0) 与 ADMIN (1) 之间自定义角色可直接用于 require_role() 和 require_auth_role() 装饰器。
管理账户和用户
普通读写、检索、会话等数据请求在 api_key 和 trusted 两种模式下都不依赖 Admin API 预注册。Admin API 仍然负责创建 account、注册用户、修改角色以及签发或重新生成 user key。
使用 root key 通过 Admin API 创建工作区和用户:
# 创建工作区 + 首个 admin
curl -X POST http://localhost:1933/api/v1/admin/accounts \
-H "X-API-Key: your-secret-root-key" \
-H "Content-Type: application/json" \
-d '{"account_id": "acme", "admin_user_id": "alice"}'
# 返回: {"result": {"account_id": "acme", "admin_user_id": "alice", "user_key": "..."}}
# 注册普通用户(ROOT 或 ADMIN 均可)
curl -X POST http://localhost:1933/api/v1/admin/accounts/acme/users \
-H "X-API-Key: your-secret-root-key" \
-H "Content-Type: application/json" \
-d '{"user_id": "bob", "role": "user"}'
# 返回: {"result": {"account_id": "acme", "user_id": "bob", "user_key": "..."}}受信部署也可以通过受信网关调用 Admin API,目前支持两种方式:
- 携带受信部署自身的
root_api_key。对于/api/v1/admin/*,服务端校验该 key 后会将请求视为 ROOT。 - 如果 Admin 路由指向具体 account/user,也可以同时携带
X-OpenViking-Account+X-OpenViking-User。这些 header 必须与目标 URL 匹配,并会保留为请求身份;授权仍来自受信root_api_key。
下面是“受信上游身份”这种方式的示例:
# 首先,注册网关管理员(在 api_key 模式下执行一次)
curl -X POST http://localhost:1933/api/v1/admin/accounts \
-H "X-API-Key: your-secret-root-key" \
-H "Content-Type: application/json" \
-d '{"account_id": "platform", "admin_user_id": "gateway-admin"}'
# 如果它需要跨 account 的管理权限,再提升为 root
curl -X PUT http://localhost:1933/api/v1/admin/accounts/platform/users/gateway-admin/role \
-H "X-API-Key: your-secret-root-key" \
-H "Content-Type: application/json" \
-d '{"role": "root"}'
# 然后,在 trusted 模式下使用该身份调用 Admin API
curl -X POST http://localhost:1933/api/v1/admin/accounts \
-H "X-API-Key: your-secret-root-key" \
-H "X-OpenViking-Account: platform" \
-H "X-OpenViking-User: gateway-admin" \
-H "Content-Type: application/json" \
-d '{
"account_id": "acme",
"admin_user_id": "alice"
}'客户端使用
OpenViking 支持两种方式传递 API Key:
X-API-Key 请求头
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
-H "X-API-Key: <user-key>"Authorization: Bearer 请求头
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
-H "Authorization: Bearer <user-key>"Python SDK(HTTP)
import openviking as ov
client = ov.SyncHTTPClient(
url="http://localhost:1933",
api_key="<user-key>",
)CLI(通过 ovcli.conf)
{
"url": "http://localhost:1933",
"api_key": "<user-key>"
}如果使用普通 user key 或 admin key,account 和 user 可以省略,因为服务端可以从 key 反查出来;如果使用 trusted 模式,则建议明确配置。
CLI 覆盖参数
openviking --account acme --user alice ls viking://使用 --sudo 和 Root API Key
CLI 支持在 ovcli.conf 中同时配置 api_key(用于普通用户操作)和 root_api_key(用于管理员操作):
{
"url": "http://localhost:1933",
"api_key": "<user-key>",
"root_api_key": "<root-key>"
}当需要执行管理员命令(admin、system、reindex)时,使用 --sudo 标志提升权限:
# 列出所有账户(需要 root 权限)
ov --sudo admin list-accounts
# 重新索引内容
ov --sudo reindex viking://
# 系统命令
ov --sudo system status--sudo 标志:
- 仅适用于管理员命令:
admin、system、reindex - 用于非管理员命令时会报错
ovcli.conf中未配置root_api_key时会报错- 请求时使用
root_api_key替代api_key
租户数据访问
租户级数据 API(如 ls、find、resources、sessions 等)在 api_key 模式下必须使用绑定了 account/user 的 key。这个 key 可以是 USER key,也可以是 ADMIN key;ADMIN key 会以它自己的 user 身份访问数据,不能通过 X-OpenViking-Account / X-OpenViking-User 切换身份。
ROOT key 没有绑定租户 user,因此在 api_key 模式下不能访问租户级数据 API。 如果部署需要由上游网关断言 account / user,请使用 trusted 模式,而不是在 root key 请求上携带身份 header。
ovcli.conf
{
"url": "http://localhost:1933",
"auth_mode": "trusted",
"api_key": "your-trusted-server-key",
"account": "acme",
"user": "alice"
}Trusted 模式
Trusted 模式不会查 user key,而是直接信任每个请求显式携带的身份请求头:
{
"server": {
"auth_mode": "trusted",
"host": "127.0.0.1"
}
}Trusted 模式规则:
- 普通数据访问不需要先注册 user key,也不依赖 user key 分发流程
- 租户级请求必须包含
X-OpenViking-Account和X-OpenViking-User - 受信上游也可以发送
X-OpenViking-Role: user或X-OpenViking-Role: admin断言请求角色。该请求头只有在配置了root_api_key且请求携带匹配 API Key 时才会生效。root不是允许的断言值;ROOT 只保留给已校验的 Admin API 回退路径 /api/v1/admin/*是特例:当请求携带已配置的root_api_key时,trusted 模式会将请求视为 ROOT。显式 account/user header 只有在完整且与目标 URL 匹配时才允许- 普通 trusted 数据 API 的角色优先使用经过授权的
X-OpenViking-Role;未提供该请求头时,通过在 APIKeyManager 中查找 account/user 确定。如果用户存在,使用其配置的角色;否则默认为USER - trusted 身份完全来自请求头,而不是 user key;如果同时配置了
root_api_key,它表示“这个上游是被允许的 trusted 调用方” - 如果同时配置了
root_api_key,每个请求仍然必须带匹配的 API Key - 只应部署在受信网络边界之后,或由身份注入网关统一转发
这意味着:
trusted不是开发模式trusted下的普通读写、检索、会话访问不需要先走 Admin API 注册流程trusted模式下,携带已配置root_api_key的受信上游可以调用 Admin APItrusted模式下,创建 account 或注册用户的 Admin API 响应不会返回user_keyroot可以创建/删除 account 并修改角色;admin可以管理自己 account 下的用户;user不能调用 Admin API- 非 localhost 部署要在 trusted 模式下使用 Admin API,需要配置
root_api_key,并在每个管理请求中携带它
curl
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
-H "X-OpenViking-Account: acme" \
-H "X-OpenViking-User: alice"Python SDK
import openviking as ov
client = ov.SyncHTTPClient(
url="http://localhost:1933",
account="acme",
user="alice",
)Dev 模式
当 auth_mode = "dev"(或未配置 root_api_key 时自动推导)时,认证禁用,所有请求以 ROOT 身份访问 default account。此模式仅允许在服务器绑定 localhost 时使用(127.0.0.1、localhost 或 ::1)。如果 host 设置为非回环地址(如 0.0.0.0)且使用 dev 模式,服务器将拒绝启动。
{
"server": {
"host": "127.0.0.1",
"port": 1933
}
}或显式配置:
{
"server": {
"auth_mode": "dev",
"host": "127.0.0.1",
"port": 1933
}
}安全提示: 默认
host为127.0.0.1。如需将服务暴露到网络,必须配置root_api_key。
角色与权限
| 角色 | 作用域 | 能力 |
|---|---|---|
| ROOT | 全局 | 全部操作 + Admin API(创建/删除工作区、管理用户) |
| ADMIN | 所属 account | 常规操作 + 管理所属 account 的用户 |
| USER | 所属 account | 常规操作(ls、read、find、sessions 等) |
在 trusted 模式下,普通租户请求默认会解析为 USER;如果该 account/user 已注册更高角色,或网关在携带已配置 root API key 的请求中断言 X-OpenViking-Role: admin,则使用更高角色。X-OpenViking-Role: root 会被拒绝。对于 Admin 路由,在没有显式身份时还支持 trusted ROOT 回退。
无需认证的端点
/health 端点始终不需要认证,用于负载均衡器和监控工具检查服务健康状态。
curl http://localhost:1933/healthAdmin API 参考
| 方法 | 端点 | 角色 | 说明 |
|---|---|---|---|
| POST | /api/v1/admin/accounts | ROOT | 创建工作区 + 首个 admin |
| GET | /api/v1/admin/accounts | ROOT | 列出所有工作区 |
| DELETE | /api/v1/admin/accounts/{id} | ROOT | 删除工作区 |
| POST | /api/v1/admin/accounts/{id}/users | ROOT, ADMIN | 注册用户 |
| GET | /api/v1/admin/accounts/{id}/users | ROOT, ADMIN | 列出用户 |
| DELETE | /api/v1/admin/accounts/{id}/users/{uid} | ROOT, ADMIN | 移除用户 |
| PUT | /api/v1/admin/accounts/{id}/users/{uid}/role | ROOT | 修改用户角色 |
| POST | /api/v1/admin/accounts/{id}/users/{uid}/key | ROOT, ADMIN | 重新生成 user key |
