加密指南
本指南介绍如何在 OpenViking 中启用和使用静态数据加密功能。
概述
OpenViking 可以按账户加密存储中新写入的文件。加解密由存储层处理,客户端沿用现有 API:
- 透明加密:API 无变化,应用层无感知
- 多租户隔离:不同账户使用独立密钥
- 三种密钥提供程序:Local、Vault、火山引擎 KMS
- 向后兼容:未加密的旧文件仍可正常读取
加密功能的概念说明见 数据加密。
主备存储中的加密
主备存储复用同一套透明加密机制。加密仍在 RAGFS 内部完成,Python SDK、HTTP API 和 CLI 不需要处理加解密。
规则:
- 全局
encryption.enabled=true时,primary backend 必须加密。 - backup backend 可以通过自己的
encryption.enabled控制是否加密。 - V2 多写 metadata 存储在 raw primary,不经过
EncryptionWrappedFS。 - OpenViking 不提供也不需要公开的加解密 API 来操作这些内部文件。
更多主备存储配置见 主备存储指南。
快速开始
1. 初始化根密钥(Local 模式)
ov system crypto init-key --output-file ~/.openviking/master.key2. 配置加密
将下面的加密配置合并到 ~/.openviking/ov.conf,保留已有模型和服务端配置:
{
"encryption": {
"enabled": true,
"provider": "local",
"local": {
"key_file": "~/.openviking/master.key"
}
},
"storage": {
"workspace": "./data"
}
}3. 验证
修改加密配置后重启服务,再对该服务运行示例。在运行脚本的环境中安装 Python SDK。
from pathlib import Path
from openviking_sdk import SyncHTTPClient
def test():
# 启用认证时,将 OPENVIKING_API_KEY 设置为绑定租户身份的 user/admin key。
client = SyncHTTPClient(url="http://localhost:1933")
try:
client.initialize()
sample = Path("./encrypted-sample.txt")
sample.write_text("Hello, encrypted world!", encoding="utf-8")
imported = client.add_resource(
path=str(sample),
wait=True,
timeout=120,
)
results = client.find(
query="encrypted", target_uri=imported["root_uri"]
)
print(f"找到 {len(results.get('resources', []))} 个资源")
finally:
client.close()
test()示例会等待导入处理完成并检查检索;检索成功本身不能证明文件已加密。请按下方“验证加密”的文件内容检查步骤确认存储文件头。
API Key 哈希配置
文件加密和 API Key 哈希是两项独立配置:
| 加密层 | 配置项 | 算法 | 可逆性 | 说明 |
|---|---|---|---|---|
| 文件层 | encryption.enabled | AES-GCM | 可逆 | 保护整个存储文件 |
| API key 字段层 | encryption.api_key_hashing.enabled | Argon2id | 不可逆 | 保护 API key 本身 |
默认行为
默认情况下,encryption.api_key_hashing.enabled = false:
- API key 以明文存储在 JSON 文件中
- 如果
encryption.enabled = true,整个文件会被 AES-GCM 加密保护 ov admin list-users可以显示完整的 API key- 如果
encryption.enabled = true且未启用 API key 哈希,服务端启动时会输出一条说明此情况的 INFO 日志
启用 Argon2id 哈希
启用 Argon2id 单向哈希后,服务端不再保存可还原的 API Key 明文:
{
"encryption": {
"enabled": true,
"api_key_hashing": {
"enabled": true
}
}
}注意:启用后:
- API key 使用 Argon2id 单向哈希存储
- 无法从哈希值还原出明文 key
ov admin list-users只显示key_prefix而不是完整的 API key- 只有在创建用户或重新生成 key 时才能看到明文 key
配置示例
{
"encryption": {
"enabled": true,
"provider": "local",
"local": {
"key_file": "~/.openviking/master.key"
},
"api_key_hashing": {
"enabled": false
}
}
}密钥提供程序选择
| 提供程序 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Local | 开发环境、单节点部署 | 简单,无需外部服务 | 需要管理本地文件权限和独立密钥备份 |
| Vault | 生产环境、多云部署 | 企业级密钥管理,支持版本控制 | 需要部署和维护 Vault |
| Volcengine KMS | 火山引擎云部署 | 云原生密钥管理服务 | 仅限火山引擎环境 |
Local 模式详细指南
初始化根密钥
# 生成并保存到指定路径
ov system crypto init-key --output-file ~/.openviking/master.key
# 或者使用简短命令
ov system crypto init-key -f ~/.openviking/master.key输出示例:
✓ Root key generated successfully
✓ Saved to: /Users/you/.openviking/master.key安全提示
- ⚠️ 妥善保管
master.key文件 - 建议设置文件权限为
600(仅所有者可读写) - 定期备份密钥文件
- 不要将密钥文件提交到版本控制系统
配置示例
{
"encryption": {
"enabled": true,
"provider": "local",
"local": {
"key_file": "~/.openviking/master.key"
}
}
}Vault 模式详细指南
前置条件
- 已部署 HashiCorp Vault 服务,并在服务端 Python 环境安装
hvac - 已启用 Transit 引擎
- 有足够权限的 Vault Token
配置 Vault
- 启用 Transit 引擎(如果尚未启用):
vault secrets enable transit- 启用 KV 引擎(如果尚未启用):
# KV v2(推荐)
vault secrets enable -path=secret -version=2 kv
# 或 KV v1
vault secrets enable -path=secret -version=1 kv按实际部署选择一条 KV 命令,不要两条都执行。下面使用 secret 挂载点和 KV v2。先由管理员创建 Transit key:
vault write -f transit/keys/openviking-root-key type=aes256-gcm96- 配置 OpenViking:
{
"encryption": {
"enabled": true,
"provider": "vault",
"vault": {
"address": "https://vault.example.com:8200",
"token": "hvs.xxxxxxxxxxxxxxxxxxxxx",
"mount_point": "transit",
"kv_mount_point": "secret",
"kv_version": 2,
"root_key_name": "openviking-root-key",
"encrypted_root_key_key": "openviking-encrypted-root-key"
}
}
}配置参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
address | Vault 服务器地址 | 必需 |
token | Vault 认证令牌 | 必需 |
mount_point | Transit 引擎挂载路径 | "transit" |
kv_mount_point | KV 引擎挂载路径 | "secret" |
kv_version | KV 引擎版本(1 或 2) | 1 |
root_key_name | Transit 引擎中的密钥名称 | "openviking-root-key" |
encrypted_root_key_key | KV 引擎中存储加密根密钥的路径 | "openviking-encrypted-root-key" |
Vault 权限建议
对于上面的配置,服务 token 需要读取 Transit key 元数据、加解密权限,以及保存封装根密钥的 KV 读写权限。提前创建引擎和 Transit key 后,可参考:
path "auth/token/lookup-self" {
capabilities = ["read"]
}
path "transit/keys/openviking-root-key" {
capabilities = ["read"]
}
path "secret/data/openviking-encrypted-root-key" {
capabilities = ["read", "create", "update"]
}
path "transit/encrypt/openviking-root-key" {
capabilities = ["update"]
}
path "transit/decrypt/openviking-root-key" {
capabilities = ["update"]
}使用 KV v1 时,将 secret/data/openviking-encrypted-root-key 改为 secret/openviking-encrypted-root-key。provider 还会检查 sys/mounts;权限不足会记录警告,Transit 已启用时不会因此停止启动。
Volcengine KMS 模式详细指南
前置条件
- 已开通火山引擎 KMS 服务
- 已创建对称密钥
- 有有效的 Access Key 和 Secret Key
创建 KMS 密钥
- 访问 火山引擎 KMS 控制台
- 点击"创建密钥"
- 选择"对称密钥",算法选择
AES_256 - 记录密钥 ID
配置 OpenViking
{
"encryption": {
"enabled": true,
"provider": "volcengine_kms",
"volcengine_kms": {
"key_id": "d926aa0d-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"region": "cn-beijing",
"access_key": "AKLTxxxxxxxxxxxxxxxxxx",
"secret_key": "Tmpxxxxxxxxxxxxxxxxxxxxxx",
"endpoint": null,
"key_file": "~/.openviking/openviking-volcengine-root-key.enc"
}
}
}配置参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
key_id | KMS 密钥 ID | 必需 |
region | 区域 | 必需 |
access_key | Access Key | 必需 |
secret_key | Secret Key | 必需 |
endpoint | 自定义 KMS 端点(可选) | null(使用默认端点) |
key_file | 加密根密钥本地缓存文件路径 | "~/.openviking/openviking-volcengine-root-key.enc" |
权限建议
为 Access Key 配置最小权限:
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt"
],
"Resource": [
"trn:kms:*:*:key/d926aa0d-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
]
}
]
}验证加密
方法一:检查文件内容
检查物理后端文件,API 返回的内容已经解密。下面的路径需换成实际文件路径。加密文件以魔术数 OVE1 开头:
# 查看文件前 4 字节
hexdump -C ./data/agfs/your-file | head -1加密文件:
00000000 4f 56 45 31 01 01 00 00 00 20 8a 7b 2c 9d 1e |OVE1..... .{,..|(前 4 字节是 4f 56 45 31 = "OVE1")
未加密文件:
00000000 7b 22 63 6f 6e 74 65 6e 74 73 22 3a 5b 7b 22 70 |{"contents":[{"p|方法二:重启后读回
重启前后,通过 API 读取同一份已导入文件,确认内容一致,再按上面的方法核对物理存储文件头。这能检查部署是否重新加载了原密钥,并能读取已有密文。
内部 provider 调用抛出异常不能直接当作加密验证通过。参数错误、依赖缺失和网络错误都可能在解密前失败。
迁移说明
从无加密迁移到有加密
启用加密不会改写已有明文文件。为了向后兼容,这些文件仍可读取;新写入的数据会使用加密。如需加密已有公开 scope,应通过 OVPack 将其迁移到全新的空加密存储环境:
- 停止业务写入,在原未加密环境运行时创建逻辑备份:
ov backup ./backups/before-encryption.ovpack- 停止 OpenViking,启用加密,并将存储配置指向全新的空 workspace/backend。验证完成前保留原数据和加密密钥备份。
- 启动加密环境。API Key 模式下,先创建目标 account 和持有 admin key 的恢复操作用户,再让 CLI 使用该 key 连接目标环境,参见 全量备份和恢复。恢复过程会通过加密存储层写入 package 内容:
创建 account 会生成 scope 目录,因此 fail 会拒绝这次恢复。仅在确认目标只有新建 account 的预置内容后,使用下方的 overwrite。如果已有业务数据,先停止操作,按 OVPack 指南备份目标并审查冲突。
ov restore ./backups/before-encryption.ovpack --on-conflict overwrite- 切流前验证资源、用户、session 和索引数据。OVPack 不包含 queue、upload、lock、watch 和 relation 文件等运行时/内部状态,这些内容需要单独重建或验证。
支持的 scope 和恢复选项详见 OVPack 导入与导出。
切换密钥提供程序
保持旧 provider 和密钥可用,导出逻辑 OVPack 备份。按上面的迁移步骤,在使用新 provider 的独立空环境恢复,核对内容、权限和重建后的索引,再切换流量。直接修改原环境的 provider 配置不会重新加密已有文件。
故障排除
密钥文件找不到
Error: Key file not found: ~/.openviking/master.key解决方案:
- 检查文件路径是否正确
- 使用绝对路径
- 确保
~被正确展开(使用expanduser())
Vault 连接失败
Error: Failed to connect to Vault解决方案:
- 检查 Vault 服务是否运行
- 验证
address配置 - 检查网络连接和防火墙
- 确认 Token 有效且未过期
火山 KMS 认证失败
Error: Invalid credentials解决方案:
- 检查 Access Key 和 Secret Key 是否正确
- 确认密钥有足够权限
- 验证区域配置正确
已有密文无法读取
检查原根密钥、provider 配置、account 身份和密文是否仍然完整。Vault 需要保留 Transit key 和存放封装根密钥的 KV 条目;KMS 需要保留 KMS key 和本地封装密钥文件。不要通过生成新根密钥修复旧密文的读取问题。
部分读取会先加载并校验整个加密文件,再返回所需的明文切片。部分读取返回密文时,记录服务版本,在测试副本上比较完整读取与部分读取,核对存储加密配置和相关修复后再升级。保留原数据及密钥,以便回退。
相关文档
Vault 参考:KV v2、Transit API。