CipherFS
开发中 · 未发布 · 格式可能变化

凭据与密封

存放点配置只在加密的本机行中保存 credential_ref(来源与精确查找名),不保存秘密。 来源定义放在本机配置中,文件来源必须位于所有受管仓库之外。显式引用缺失、过期、 被撤回或无效时明确失败,不回退 ENV、profile 或云元数据服务。

来源

kind配置查找
environment无额外字段name 是精确环境变量名,每次重新读取。
files绝对 directory_pathname 是单一文件名;Unix 为当前用户所有、单链接、0400/0600 的普通文件,父目录受信任且不可由组或其他人写入;拒绝符号链接。
systemd无额外字段每次读取当前 CREDENTIALS_DIRECTORY 下的 name,沿用文件校验。
keyring公开 service 名macOS Security、Windows Credential Manager、Linux Secret Service;后台不弹窗、不解锁集合,条目由用户另行配置。
httpsendpoint_url、bearer_token_ref,可选公开 CA certificate_path将 name 作为单一路径段发 HTTPS GET,Bearer 重新读取;禁止跳转,连接 3 秒、总计 10 秒截止。

最多 64 个来源,依赖深度最多 8,拒绝未知依赖与环。响应非空且最多 256 KiB。 目录被替换后重新校验,拒绝指向仓库内部的规范化别名。S3 来源返回 JSON: access_key_secret、secret_key_secret,可选 session_token_secret、expires_at_epoch_s; 拒绝未知字段,每个凭据分量最多 65536 字节。密码为精确 UTF-8 字节,不自动去换行; 服务解封密钥为恰好 32 个原始字节,不进行文本或 base64 转换。

已注册 service 封装后可使用:

{
  "secret_sources": {"files":{"kind":"files","directory_path":"/run/cipherfs-secrets"}},
  "vaults": [{"name":"personal","vault_path":"/srv/cipherfs/personal",
    "auto_unseal":{"kind":"key","source_id":"service","credential_ref":{"source":"files","name":"service-key"}}}],
  "listeners":[{"listen_address":"127.0.0.1:3000"}]
}

首次注册在已认证 Core 中调用 add_unlock_key_source;外部文件用 owner::read_credential_file 读取并保持 Zeroizing guard,密钥不要放进仓库。 密码来源将 kind 改为 password 并省略 source_id;显式 env:NAME 密码简写也会重试。 credential_bindings 可在保存之前把位置及可选 store_id 绑定到引用。CLI 持久注册:

cipherfs store add s3 --vault /srv/cipherfs/personal --bucket example-bucket \
  --region us-east-1 --prefix team --credential-source files --credential-name s3-writer

桌面 S3 表单与公开同步 API 只接受引用,拒绝直接填写 access/secret 字段。 私有原生凭据注入协议仍像进程内 C/Python/Go override 一样,限受认证本机传输和当前会话。

密封与恢复

serve 先密封取得租约、发布私有发现,再尝试来源。失败保持进程存活,health 为 sealed、 ready 返回 503;重试从 1 秒增长,最多 30 秒。成功建立新会话,手动密封不会立即自动解封。 cipherfs seal --vault PATH 撤销会话、停止同步与归属挂载、排空已接纳操作并清除密钥,保留 原租约和端点;cipherfs unseal 使用通常的密码输入,--configured 仅经私有端点取配置来源。 旧句柄、快照、写入、JWT、凭据上下文不会因解封复活。logout/lock 仍关闭归属并释放发现。

POST /api/v1/unseal 接受 kind=password/password_secret 或 kind=recovery/recovery_key_secret 证明;kind=configured 限私有端点,远端不能靠触发宿主来源获取会话。 POST /api/v1/seal 要求当前会话。错误证明不撤销已有有效会话。 Core 返回 Sealed,原生错误码 32,HTTP 分类 SEALED/503。

SyncedVault::set_idle_timeout(Some(Duration)) 按用户操作闲置密封,后台轮询不算活动;None 关闭策略。解封要显式传入新 provider,并重新启用同步。阻塞门面与绑定使用可选毫秒; unseal/unseal_with_unlock_key 成功后需重新配置来源/凭据,不悄悄回退 ENV。绑定也提供密封打开、 独立服务密钥封装增删和来源配置。密码、恢复与服务封装可并存,都在 metadata schema 1 的 unlock_wraps 表里;封装格式见 FORMAT.md 第 5.5 节。

长期原生仓库密钥与 S3/WebDAV 凭据使用独立锁页,失败返回错误;先清零再解锁页面。 Linux 禁止 dumpable 且 core 的软硬限制均为 0;macOS 禁 core 并锁页。这些限制不可逆且影响 整个嵌入进程。临时密码学、HTTP、第三方及调用方缓冲无法全部保证清零/锁页;应用 provider 仍负责自身秘密存储。运行中 root 和虚拟机宿主读内存均不在防护范围,来源差异表见 README。

写入设备无删除权

为写入设备使用独立 S3 角色,只允许前缀下 GetObject/PutObject 及带 prefix 条件的 ListBucket, 显式拒绝 DeleteObject/DeleteObjectVersion,并拒绝该角色改生命周期、桶策略、版本状态或删除桶。 完整可替换 bucket/role/team 前缀的 JSON 模板见英文页, 依据 AWS 桶策略例子 与权限映射。 生命周期、管理员、GC 身份另行控制;禁止删除不阻止有 Put 权限者覆盖对象。

cipherfs store check-permissions --vault PATH --id ID 先有界 LIST 验证凭据,再 HEAD 确认随机 探针键不存在,只尝试 DELETE 该不存在的键;不 PUT,不删已知业务对象。 只把明确 AccessDenied 且随后 LIST 仍成功算 delete_denied=true。过期、撤销及其他错误不算成功; 删除允许则报告 false,CLI 非零退出。探测只反映一个命名空间,不能证明整个账户策略或版本删除权。 版本桶允许 DELETE 时仍可能生成删除标记。

仓库中的源文件