如何结合Dotenvx保护DuckDB的Secrets
DuckDB 1.4版本增加了数据库加密功能, 截止目前为止,DuckDB涉及到Secrets的主要包括如下:
- 原生Secret:如S3和兼容存储服务的的AK/SK,http资源访问的token,huggingface和数据库访问的账号密码等
- DuckLake:主要是MySQL/PostgreSQL元信息数据库的账号密码,S3服务的AK/SK等,这个是DuckLake的核心配置
- 加密数据库:是对整个数据库的加密,使用AES 256进行加密,加密密码由用户提供
DuckDB虽然提供了Secret的管理能力,但是并没有达到安全的需求,而且用户使用体验也有一些问题,如:
- Temporary Secrets:临时Secret,保存在内存中,进程退出后就会丢失,所以要每次都要创建,如S3的AK/SK,我都是每次创建,反复copy创建Secret的SQL。
- Persistent Secrets: 持久化Secret,默认以未加密的方式保存在
$HOME/.duckdb/stored_secrets
目录下
鉴于DuckDB的Secret管理的加密特性缺失,所以也有不少人建议使用KMS来进行加密,而且好像也没有第三方的扩展来支持这一点。
此外如果你稍不留意的话,你创建的Secret的SQL语句就会被记录到$HOME/.duckdb_history
文件中,这个文件也是明文保存的。
既然Dotenvx能够使用管理.env
文件中的Secrets,那么能否结合Dotenvx来保护DuckDB的Secrets呢?
首先让我们看一个管理DuckDB Secrets的.env.duckdb
的样例:
DUCKDB__HTTP_SECRET=secret
DUCKDB__HTTP_SECRET__TYPE=http
DUCKDB__HTTP_SECRET__BEARER_TOKEN=xxxx
再看一个加密数据库的样例:
DUCKDB__SECRET_DB=attach
DUCKDB__SECRET_DB__TYPE=duckdb
DUCKDB__SECRET_DB__URL=encrypted.db
DUCKDB__SECRET_DB__ENCRYPTION_KEY=123456
从上述的代码中,我们采用__
作为层级分隔符,这样就可以将复杂的结构体转换为环境变量,
详细的方法大家可以参考: Structured data in environment variables
所以DuckDB的secret的配置就可以从SQL方式转换为标准的配置项,结构如下:
DUCKDB__OBJECT_NAME=attach/secret
DUCKDB__OBJECT_NAME_TYPE=secret_type/db_type
DUCKDB__OBJECT_NAME_ATTRIBUTE_NAME=value
考虑到该配置项主要是针对DuckDB的,所以Dotenvx对DuckDB添加了.env.duckdb
的支持,当然你也可以使用.env
文件。
如果是不同的项目,你只需要创建不同项目的.env.duckdb
文件即可。
最后我们使用dotenvx link bin/duckdb
创建DuckDB CLI的软链接,然后运行./bin/duckdb
即可。
Dotenvx就会自动加载.env.duckdb
文件中的加密配置项,然后转换为SQL,然后通过--cmd sql
参数传递给DuckDB CLI,
这样就完成了DuckDB的Secret的创建。
提示: 通过该方式创建的Secret是临时的,进程退出后就会丢失,而且也不会保存到$HOME/.duckdb_history
文件中,这样就避免了Secret泄露的问题。