密钥管理器(Secrets Manager)为所有使用密钥的后端提供了统一的用户界面。密钥信息可以被限定范围,因此不同的存储前缀可以有不同的密钥信息,例如允许在单个查询中连接跨组织的数据。密钥也可以持久化,这样就不需要在每次启动DuckDB时都指定它们。
密钥类型
在DuckDB中是密钥分类管理的,它们的类型标识它们用于哪个服务。目前提供的云服务如下:
- AWS S3 (
S3
), through thehttpfs
extension - Azure Blob Storage (
AZURE
), through theazure
extension - Cloudflare R2 (
R2
), through thehttpfs
extension - Google Cloud Storage (
GCS
), through thehttpfs
extension - Hugging Face (
HUGGINGFACE
), through thehttpfs
extension - MySQL (
MYSQL
), through themysql
extension - PostgreSQL (
POSTGRES
), through thepostgres
extension
对于每种类型,都有一个或多个“密钥提供程序”来指定如何创建密钥。secret也可以有一个可选的作用域,它是secret应用的文件路径前缀。在为路径获取密钥时,将密钥范围与路径进行比较,并返回与路径匹配的密钥。在有多个匹配密钥的情况下,选择最长的前缀。
密钥管理
可以使用CREATE SECRET SQL语句创建密钥。密钥可以是暂时的,也可以是持久的。默认情况下使用临时密钥,并且在DuckDB实例的生命周期内存储在内存中,类似于以前的设置工作方式。持久密钥以未加密的二进制格式存储在~/.duckdb/stored_secrets
目录中。在启动DuckDB时,将从该目录读取持久密钥并自动加载。
临时密钥
要创建一个临时的无作用域secret来访问S3,我们现在可以使用以下命令:
CREATE SECRET my_secret (TYPE S3,KEY_ID 'my_secret_key',SECRET 'my_secret_value',REGION 'my_region'
);
注意,我们在这里隐式地使用默认的CONFIG秘密提供程序。
持久密码
为了在DuckDB数据库实例之间持久化秘密,我们现在可以使用CREATE PERSISTENT SECRET命令,例如:
CREATE PERSISTENT SECRET my_persistent_secret (TYPE S3,KEY_ID 'my_secret_key',SECRET 'my_secret_value'
);
默认情况下,这将把秘密(未加密)写入~/.duckdb/stored_secrets
目录中。修改secrets目录,命令如下:
SET secret_directory = 'path/to/my_secrets_dir';
注意,设置home_directory配置选项的值对密钥文件的位置没有影响。
创建同类型多个密钥
如果一个服务类型存在两个密钥,则可以使用作用域来决定应该使用哪一个。例如:
CREATE SECRET secret1 (TYPE S3,KEY_ID 'my_secret_key1',SECRET 'my_secret_value1',SCOPE 's3://my-bucket'
);CREATE SECRET secret2 (TYPE S3,KEY_ID 'my_secret_key2',SECRET 'my_secret_value2',SCOPE 's3://my-other-bucket'
);
现在,如果用户从s3://my-other-bucket/something查询某些内容,则会自动为该请求选择secret secret2。要查看正在使用的是哪个密钥,可以使用which_secret
标量函数,它接受路径和密钥类型作为参数:
FROM which_secret('s3://my-other-bucket/file.parquet', 's3');
查询密钥
可以使用内置的表生成函数列出秘密,例如,通过使用duckdb_secrets()表函数:
FROM duckdb_secrets();
删除密钥
可以使用DROP SECRET语句删除密钥,例如:
DROP PERSISTENT SECRET my_persistent_secret;
密钥应用示例
mysql扩展允许DuckDB直接从运行的mysql实例中读写数据。数据可以直接从底层MySQL数据库查询。数据可以从MySQL表加载到DuckDB表,反之亦然。下面通过mysql扩展介绍如何应用密钥。
安装加载扩展
通过下面命令安装并加载mysql扩展:
INSTALL mysql;
LOAD mysql;
直接附加mysql
为了让DuckDB访问mysql,可以通过attach命令附加mysql数据库:
ATTACH 'host=localhost user=root port=0 database=mysql' AS mysqldb (TYPE MYSQL);
USE mysqldb;
更多连接参数可以参考官网文档,这里直接硬代码编写连接信息。下面通过密钥管理器实现连接。
密钥管理器配置
首先创建MySQL密钥管理器:
CREATE SECRET (TYPE MYSQL,HOST '127.0.0.1',PORT 0,DATABASE mysql,USER 'mysql',PASSWORD ''
);
当调用ATTACH时,将使用来自密钥的信息。我们可以将连接字符串保留为空,以使用存储在密钥管理器中的所有信息。
ATTACH '' AS mysql_db (TYPE MYSQL);
我们可以使用连接字符串来覆盖单个选项。例如,要在仍然使用相同凭据的情况下连接到不同的数据库,我们可以按以下方式仅覆盖数据库名称。
ATTACH 'database=my_other_db' AS mysql_db (TYPE MYSQL);
缺省情况下,创建的密钥是临时的。可以使用CREATE PERSISTENT SECRET命令持久化秘密。持久秘密可以跨会话使用。
多个密钥
命名密钥可以用来管理到多个MySQL数据库实例的连接,可以在创造时给密钥赋予名称。
CREATE SECRET mysql_secret_one (TYPE MYSQL,HOST '127.0.0.1',PORT 0,DATABASE mysql,USER 'mysql',PASSWORD ''
);# 使用Attach命令时显示引用
ATTACH '' AS mysql_db_one (TYPE MYSQL, SECRET mysql_secret_one);
总结
DuckDB 的密码管理器(Secrets Manager)作用是管理诸如数据库连接密码、API 密钥、令牌等敏感信息。它提供了相对安全的方式来存储、访问这些信息,避免在代码或配置文件中以明文形式暴露敏感数据,从而增强了数据安全性。例如,在连接数据库或者调用外部服务时,可以通过这个管理器来安全地获取和使用所需的密钥或密码。