news 2026/9/13 23:28:57

Data Formulator 凭证保险箱(Credential Vault)深度解析:加密存储、安全模型与部署实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Data Formulator 凭证保险箱(Credential Vault)深度解析:加密存储、安全模型与部署实践

Data Formulator 凭证保险箱(Credential Vault)深度解析:加密存储、安全模型与部署实践

【免费下载链接】data-formulator🪄 Data Formulator is an interactive AI-powered data analysis system makes it easy to connect, explore and visualize data.项目地址: https://gitcode.com/GitHub_Trending/da/data-formulator

适用版本:Data Formulator 0.7+ | 面向读者:部署运维人员、管理员、需要理解凭证保存行为的用户

Data Formulator 是面向交互式 AI 数据分析的开放系统,支持连接并探索数据库、数据湖等外部数据源。为了在服务端安全保存数据库密码、访问 token、API key 等敏感凭证,项目引入了 Credential Vault(凭证保险箱)机制。本文以 docs/docs-cn/6-credential-vault.md 为主体,结合py-src/data_formulator/auth/vault/源码与测试用例,系统讲解 Vault 的零配置启动、Fernet 加密安全模型、DataConnector 生命周期集成、TokenStore 优先级链、手动 REST API 以及 Docker 部署与密钥管理,帮助读者完整掌握凭证的安全保存与恢复策略。


1. 功能简介:Vault 到底保存什么、不保存什么

Credential Vault 用于在服务端加密保存外部数据源凭证,典型内容包括:

  • 数据库密码(MySQL、PostgreSQL、SQL Server、Kusto、MongoDB、CosmosDB 等);
  • 访问 token(Superset 等 SSO 数据源的 service token);
  • API key(BigQuery、S3、Azure Blob、Athena 等云服务的凭证)。

DataConnector 连接成功后,可以把敏感凭证保存到 vault;后续用户打开同一个连接时无需重新输入,直接由后端从 vault 解密取出并重建 loader。

需要特别强调边界:Vault只保存凭证,不保存连接卡片本身。连接卡片(connector 定义)保存在 YAML 配置文件中,按管理员全局与用户个人分两级:

DATA_FORMULATOR_HOME/connectors.yaml # 管理员全局连接 DATA_FORMULATOR_HOME/users/<identity>/connectors.yaml # 用户个人连接

注:从 data_connector.py 的create_connector实现看,用户连接除了上述users/<identity>/connectors.yaml,还会以 JSON 形式持久化到DATA_FORMULATOR_HOME/users/<identity>/connectors/<source_id>.json,二者共同构成"连接定义"层;而密码等敏感字段被_connector_config_params(data_connector.py)剥离,只把非敏感参数落盘,敏感凭证一律进入 vault。

这种"定义与凭证分离"的设计是本文理解一切后续行为的基础。


2. 零配置启动:本地开箱即用

本地使用无需任何配置。首次使用 vault 时系统自动完成两件事:

  1. 生成 Fernet 加密密钥,写入DATA_FORMULATOR_HOME/.vault_key
  2. 创建加密数据库DATA_FORMULATOR_HOME/credentials.db

首次运行后,数据目录结构大致如下:

~/.data_formulator/ ├── .vault_key ├── credentials.db ├── connectors.yaml # 可选,管理员预配置连接 └── users/ └── <identity>/ ├── connectors.yaml # 用户创建的连接 └── ...

这些文件在重启和升级后持续保留,迁移服务器时必须一起备份(详见 docs/docs-cn/7-server-migration-guide.md)。

源码级印证:密钥解析与库表结构

零配置自动化的实现位于 auth/vault/init.py 的_resolve_key:先检查CREDENTIAL_VAULT_KEY环境变量,未设置时读取.vault_key文件;若文件也不存在,则调用Fernet.generate_key()自动生成并写回文件(key_file.write_text(new_key + "\n", encoding="utf-8"))。get_credential_vault()是全局单例工厂,还有两个特殊分支:

  • 当通过disable_data_connectors禁用数据连接器时(如 ephemeral demo 部署),跳过 vault 创建;
  • 当密钥解析失败时返回None,插件退化为仅会话存储。

credentials.db的库表由 auth/vault/local_vault.py 的_init_db创建,核心为一张credentials表:

CREATE TABLE IF NOT EXISTS credentials ( user_id TEXT NOT NULL, source_key TEXT NOT NULL, encrypted_data BLOB NOT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, source_key) )

encrypted_data是经 Fernet 加密后的密文 BLOB,主键(user_id, source_key)直接对应下文"访问隔离"按身份 + 数据源 key 的设计。


3. 安全模型:Fernet 加密 + 逻辑隔离

Vault 的安全设计可归纳为下表:

方面设计
加密算法Fernet(AES-128-CBC + HMAC-SHA256)
密钥存储DATA_FORMULATOR_HOME/.vault_key,或CREDENTIAL_VAULT_KEY环境变量
数据库位置DATA_FORMULATOR_HOME/credentials.db
访问隔离(user_identity, connector_id)逻辑隔离
前端隔离明文凭证不返回前端;前端只看到连接状态、参数表单和非敏感配置
传输安全生产环境应使用 HTTPS

几个要点需要展开:

  • Vault 是逻辑隔离,不是每用户一个数据库文件。所有用户的凭证都放在同一个credentials.db中,通过user_id区分。因此服务端进程持有加密密钥,备份与权限管理应以整个DATA_FORMULATOR_HOME为单位处理
  • 加密写入store将凭证字典json.dumps后经self._fernet.encrypt(...)加密,再写入 SQLite;retrievedecryptjson.loads还原(见 local_vault.py)。若解密失败(如密钥不匹配),retrieve返回None并记录 warning,而不是崩溃。
  • 身份命名空间user_id来自 auth/identity.py 的get_identity_id(),取值形如user:alice@corp.com(OIDC 认证用户)、local:<os_username>(单用户 localhost)、browser:<uuid>(匿名浏览器 UUID)。前缀命名空间确保认证用户的数据无法通过伪造 header 访问,匿名用户也无法读取他人凭证。
  • 前端隔离:所有凭证 API 都不向浏览器返回明文。/api/credentials/list只返回"哪些 source key 存了凭证"。

传输层安全不在 vault 本身范畴:生产环境必须通过反向代理或直接配置启用 HTTPS,避免凭证在网络上明文传输。


4. DataConnector 工作流程:创建 / 重连 / 断开与删除

4.1 创建连接

用户填写连接参数后,后端依次执行:

用户填写连接参数 ↓ POST /api/connectors ↓ 后端创建用户 connector 定义 ↓ 如果参数足够,立即连接并测试 ↓ 非敏感参数写入 users/<identity>/connectors.yaml 敏感凭证加密写入 credentials.db

从源码看,create_connector(data_connector.py)会先剥离敏感参数生成default_params并持久化连接定义;随后若提供了connect_params,调用connector._connect(connect_params)建 loader 并test_connection();测试通过后调用connector._persist_credentials(connect_params),由_vault_store将完整user_params(含密码)加密写入 vault(见 data_connector.py)。注意:只有连接测试成功才会持久化凭证,避免把错误密码写进库。

4.2 重新连接

用户点击已存在的数据源卡片 ↓ 后端按 identity + connector_id 查找连接定义 ↓ 如需要凭证,则从 vault 取出并创建 loader ↓ 连接成功后进入 catalog 浏览和导入界面

实际重连逻辑在_try_auto_reconnect(data_connector.py):从 vault 取出stored_params与默认参数合并,创建 loader 并test_connection()。关键实现细节包括:

  • 重试与退避:最多尝试_RECONNECT_MAX_ATTEMPTS = 3次,退避间隔为0.5s1.0s_RECONNECT_BACKOFF_BASE = 0.5),用于扛过网络抖动、token 交换等瞬时故障;
  • 过期凭证清理:只有当所有尝试都失败时,才_vault_delete(identity)清除失效凭证;
  • 两级兜底:无 vault 凭证时,对 token/SSO 模式走_try_sso_auto_connect;对 Kusto 这类使用DefaultAzureCredential/托管身份的环境凭据连接器,走_try_ambient_reconnect直接用持久化的连接参数重连(见 data_connector.py)。

4.3 断开和删除

操作连接卡片当前 loaderVault 凭证
Disconnect保留清除清除当前服务 token/凭证
Delete删除清除删除
  • Disconnect适合临时切换账号或清理当前授权:连接定义保留,方便之后一键重连;
  • Delete表示不再需要该用户连接:连接定义、内存 loader、vault 凭证一并清除;
  • 管理员预配置的连接不能由普通用户删除:从 data_connector.py 的delete_connector看,删除用户连接时同时清除 vault 凭证并移除配置文件;管理员(admin)连接删除会返回 403。

在 TokenStore 侧,clear_service_token(token_store.py)会同时清除 Session 缓存和 vault 凭证,并对sso_exchange模式的数据源在当前浏览器会话中阻止自动重连,直到用户显式重新登录。


5. TokenStore 与 SSO:六级凭证解析优先级链

对于 Superset 等支持 SSO 或弹窗委托登录的数据源,系统并非直接使用 vault,而是通过统一的 auth/token_store.py 解析凭证。其get_access(system_id)实现了一个六级优先级链

  1. Session 中已有目标系统 token(未过期则直接返回access_token);
  2. refresh token 可续期(向token_url发起 refresh_token 换取新 token);
  3. 用 Data Formulator 的 SSO token 换取目标系统 token(sso_exchange,POST 到exchange_url);
  4. 使用弹窗委托登录保存的 token(delegated模式);
  5. 使用 vault 中保存的静态凭证(_try_vaultvault.retrieve(identity, system_id));
  6. 无可用凭证,提示用户重新授权或重新输入。

其中第 5 级的_vault_retrieve(token_store.py)会通过get_identity_id()取得当前身份,再调用 vault 单例按(identity, system_id)读取。这解释了文档中"TokenStore 会优先使用当前 Session 中的 service token 或通过 SSO exchange 获取目标系统 token,静态凭证是更靠后的兜底"的行为:动态 token 优先于静态密码,vault 主要用于没有 SSO 能力的场景或刷新链路全部失效时的最后手段。

从源码结构看,_all_auth_configs会遍历所有已注册的DATA_LOADERS,收集声明了auth_config()(mode 为sso_exchange/oauth2/delegated等)的 loader,为其建立 token 解析通道。OIDC/TokenStore 的完整开发细节见 docs/dev-guides/4-authentication-oidc-tokenstore.md。


6. 手动 API:通用凭证接口

尽管普通 DataConnector 流程无需直接调用,系统仍保留一套通用的凭证 REST API(实现于 routes/credentials.py):

方法路径用途
GET/api/credentials/list列出有存储凭证的 source key,不暴露密码
POST/api/credentials/store存储或更新凭证
POST/api/credentials/delete删除凭证

接口行为要点:

  • 全部按身份隔离:每个端点都通过get_identity_id()取得当前用户,只能读写自己的凭证;
  • /list不暴露明文:只返回{"sources": [...]},即存有凭证的 source_key 列表(见 credentials.py);
  • /store校验必填字段:缺少source_keycredentials时返回INVALID_REQUEST;vault 未配置时返回SERVICE_UNAVAILABLE(见 credentials.py)。

DataConnector 的连接、断开、删除操作会通过/api/connectors/*路由完成对应的 vault 生命周期处理,因此普通用户通常不需要直接调用上述三个端点。


7. Docker 部署:挂载数据目录 + 外部密钥注入

7.1 挂载整个数据目录

Docker 部署时只需挂载完整数据目录,密钥、凭证库、连接配置和用户数据都会包含其中:

volumes: - df-data:/root/.data_formulator

注意挂载点必须是DATA_FORMULATOR_HOME的实际路径(镜像内默认~/.data_formulator),且必须保留.vault_keycredentials.db两个文件——只挂载部分目录会导致密钥与密文分离,vault 将无法解密。

7.2 使用外部 Secret Manager 注入密钥

如果使用外部 Secret Manager(如云厂商的密钥托管服务)管理密钥,可以通过环境变量注入,避免密钥落盘:

CREDENTIAL_VAULT_KEY=<your-fernet-key>

设置后,.vault_key文件将被忽略,系统直接使用环境变量中的密钥。这为容器化部署提供了确定性密钥(_resolve_key中环境变量优先级高于文件,见 auth/vault/init.py)。


8. 生成 Vault 密钥与密钥丢失后果

需要外部生成 Fernet 密钥(例如在 CI/CD 中预生成再注入 Secret Manager)时,使用:

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

密钥丢失的后果

如果密钥丢失,credentials.db中的已保存凭证无法恢复——Fernet 的 HMAC-SHA256 完整性校验会直接拒绝解密(对应retrieveexcept Exception返回None的分支)。届时用户需要:

  • 重新输入外部数据源密码;
  • 或重新走 SSO/弹窗委托授权流程。

因此运维上的建议是:DATA_FORMULATOR_HOME(含.vault_keycredentials.dbconnectors.yaml)应整体纳入备份策略;密钥本身应像其他主密钥一样受控保管,并考虑定期轮换(轮换时需同步迁移已加密数据或接受重新授权成本)。


9. 相关文件与源码地图

Vault 功能的核心源码位于:

py-src/data_formulator/auth/vault/ ├── __init__.py # 工厂:密钥解析(env > .vault_key > 自动生成)、单例创建 ├── base.py # CredentialVault 抽象接口(store/retrieve/delete/list_sources) └── local_vault.py # LocalCredentialVault:SQLite + Fernet 实现

周边配合模块:

  • auth/token_store.py —— 六级凭证解析链,统一供 Agent、DataConnector、routes 调用;
  • auth/identity.py —— 身份解析与命名空间(user:/local:/browser:);
  • data_connector.py —— 连接生命周期与 vault 集成(_vault_store/_vault_retrieve/_vault_delete、自动重连);
  • routes/credentials.py —— 手动凭证 API;
  • tests/backend/auth/test_credential_vault.py 与 tests/backend/auth/test_credential_vault_factory.py —— 覆盖加解密、工厂密钥解析优先级、vault 未配置等分支的单元测试。

相关文档:

  • docs/docs-cn/1-data-source-connections.md
  • docs/docs-cn/7-server-migration-guide.md
  • docs/dev-guides/4-authentication-oidc-tokenstore.md
  • docs/dev-guides/5-data-connector-api.md

小结

Data Formulator 的 Credential Vault 用一条清晰的职责边界(连接定义落盘 YAML、敏感凭证加密入库)解决了多数据源场景下"免重复输入密码"与"明文凭证不落盘"的矛盾:本地单用户零配置即可启用 Fernet 加密;多用户部署按(identity, source_key)逻辑隔离;Docker/生产环境可通过CREDENTIAL_VAULT_KEY把密钥管理上移到 Secret Manager。理解密钥丢失即凭证不可恢复这一约束,并在备份、迁移(参考 docs/docs-cn/7-server-migration-guide.md)与轮换策略中把.vault_keycredentials.db作为一个整体对待,是安全运维该功能的关键。

【免费下载链接】data-formulator🪄 Data Formulator is an interactive AI-powered data analysis system makes it easy to connect, explore and visualize data.项目地址: https://gitcode.com/GitHub_Trending/da/data-formulator

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 23:28:44

8款热门AI论文写作工具横向实测,本硕博撰稿避坑实操指南

前言&#xff1a;AI 写论文乱象频发&#xff0c;实测 8 款工具理清适配边界 每到毕业季&#xff0c;本科生、硕博生都会集中寻找 AI 论文辅助工具&#xff0c;市面各类写作软件层出不穷。然而&#xff0c;这些工具普遍存在几大硬伤&#xff1a;虚假参考文献、无法匹配本校格式…

作者头像 李华
网站建设 2026/9/13 23:27:44

YOLOv5草莓目标检测实战:从数据标注到调优的完整流程

简介&#xff1a;基于YOLOv5的草莓目标检测项目&#xff0c;源自“猛犸杯”比赛赛题&#xff0c;因赛事主办方提供的数据量非常少&#xff0c;数据预处理与增强便成为提升模型准确率的关键。项目定位于人工智能、计算机、通信工程、自动化等专业方向&#xff0c;适用于在校学生…

作者头像 李华
网站建设 2026/9/13 23:27:24

第31章 咸•感应 初见

2017年的巴黎春天来得比往年晚。四月了&#xff0c;塞纳河两岸的梧桐树才开始冒出极小的芽点&#xff0c;那种绿色淡得像水彩在纸面上洇开后的第一层底色。悦儿住在大学城一间不到十二平米的宿舍里&#xff0c;房间里有一张床、一张书桌、一个塞满了书的小书架。桌面的正中间放…

作者头像 李华
网站建设 2026/9/13 23:26:54

MXNet原生实现人脸年龄性别识别全流程

简介&#xff1a;本资源是基于MXNet框架实现的高精度年龄与性别识别模型&#xff0c;面向深度学习初学者、计算机视觉开发者及AI项目实践者&#xff0c;解决人脸属性分析这一典型CV任务。资源包共28个文件&#xff0c;含13个Python源码&#xff08;涵盖数据预处理、MTNN人脸检测…

作者头像 李华
网站建设 2026/9/13 23:22:11

国产压力传感器替代:四维验证法打破pin-pin兼容误区

1. “pin-pin 兼容”不是终点&#xff0c;而是国产压力传感器替代工程的起点最近在几个工业自动化客户现场做传感器选型评估时&#xff0c;反复听到一句让我警觉的话&#xff1a;“这个国产型号和原装引脚定义一样&#xff0c;直接焊上去就能用。”——话音刚落&#xff0c;PLC…

作者头像 李华