扩展 MySQL 9.0  /  ...  /  编写 Keyring 插件

4.4.12 编写 Keyring 插件

MySQL 服务器支持一个 keyring 服务,该服务允许内部服务器组件和插件安全地存储敏感信息以供以后检索。本节描述如何编写一个服务器端 keyring 插件,该插件可被服务函数用来执行密钥管理操作。有关通用 keyring 信息,请参阅 MySQL Keyring

重要

MySQL 8.4 移除了已弃用的 keyring 插件,转而使用 keyring 组件。例如,使用 component_keyring_file 而不是 keyring_file。有关相关信息,请参阅 Keyring 组件与 Keyring 插件

此处的说明基于 MySQL 源代码分发版中的 plugin/keyring 目录中的源代码。该目录中的源文件实现了一个名为 keyring_file 的插件,该插件使用服务器主机上的本地文件进行数据存储。

要编写 keyring 插件,请在插件源文件中包含以下头文件。其他 MySQL 或通用头文件也可能需要,具体取决于插件的功能和需求。

#include <mysql/plugin_keyring.h>

plugin_keyring.h 包含 plugin.h,因此您无需显式包含后者。 plugin.h 定义了 MYSQL_KEYRING_PLUGIN 服务器插件类型以及声明插件所需的数据结构。 plugin_keyring.h 定义了特定于 keyring 插件的数据结构。

Keyring 插件与任何 MySQL 服务器插件一样,都有一个通用插件描述符(参见 第 4.4.2.1 节,“服务器插件库和插件描述符”)。在 keyring.cc 中,keyring_file 的通用描述符如下所示

mysql_declare_plugin(keyring_file)
{
  MYSQL_KEYRING_PLUGIN,     /* type                                     */
  &keyring_descriptor,      /* descriptor                               */
  "keyring_file",           /* name                                     */
  "Oracle Corporation",     /* author                                   */
  "store/fetch authentication data to/from a flat file", /* description */
  PLUGIN_LICENSE_GPL,
  keyring_init,             /* init function (when loaded)              */
  keyring_deinit,           /* deinit function (when unloaded)          */
  0x0100,                   /* version                                  */
  NULL,                     /* status variables                         */
  keyring_system_variables, /* system variables                         */
  NULL,
  0,
}
mysql_declare_plugin_end;

name 成员 (keyring_file) 指示插件名称。这是由 INFORMATION_SCHEMA.PLUGINSSHOW PLUGINS 显示的名称。

通用描述符还引用了 keyring_system_variables,这是一个将系统变量暴露给 SHOW VARIABLES 语句的结构

static struct st_mysql_sys_var *keyring_system_variables[]= {
  MYSQL_SYSVAR(data),
  NULL
};

keyring_init 初始化函数在数据文件不存在的情况下创建它,然后读取它并初始化密钥存储。 keyring_deinit 函数释放与文件关联的数据结构。

keyring_descriptor 在通用描述符中的值指向特定于类型的描述符。对于 keyring 插件,此描述符具有以下结构

struct st_mysql_keyring
{
  int interface_version;
  bool (*mysql_key_store)(const char *key_id, const char *key_type,
                          const char* user_id, const void *key, size_t key_len);
  bool (*mysql_key_fetch)(const char *key_id, char **key_type,
                          const char *user_id, void **key, size_t *key_len);
  bool (*mysql_key_remove)(const char *key_id, const char *user_id);
  bool (*mysql_key_generate)(const char *key_id, const char *key_type,
                             const char *user_id, size_t key_len);
};

特定于类型的描述符具有以下成员

  • interface_version:按照惯例,特定于类型的插件描述符从给定插件类型的接口版本开始。服务器在加载插件时检查 interface_version 以查看插件是否与其兼容。对于 keyring 插件,interface_version 成员的值为 MYSQL_KEYRING_INTERFACE_VERSION(在 plugin_keyring.h 中定义)。

  • mysql_key_store:一个将密钥混淆并存储在 keyring 中的函数。

  • mysql_key_fetch:一个将密钥去混淆并从 keyring 中检索的函数。

  • mysql_key_remove:一个从 keyring 中删除密钥的函数。

  • mysql_key_generate:一个生成新随机密钥并将其存储在 keyring 中的函数。

对于 keyring_file 插件,特定于类型的描述符如下所示

static struct st_mysql_keyring keyring_descriptor=
{
  MYSQL_KEYRING_INTERFACE_VERSION,
  mysql_key_store,
  mysql_key_fetch,
  mysql_key_remove,
  mysql_key_generate
};

Keyring 插件实现的 mysql_key_xxx 函数类似于 keyring 服务 API 公开的 my_key_xxx 函数。例如,mysql_key_store 插件函数类似于 my_key_store keyring 服务函数。有关 keyring 服务函数参数以及它们的使用方式的信息,请参阅 Keyring 服务

要编译和安装插件库文件,请使用 第 4.4.3 节,“编译和安装插件库” 中的说明。要使库文件可用,请将其安装到插件目录中(由 plugin_dir 系统变量命名的目录)。对于 keyring_file 插件,当您从源代码构建 MySQL 时,它将被编译和安装。它也包含在二进制分发版中。构建过程会生成一个共享对象库,其名称为 keyring_file.so.so 后缀可能因平台而异)。

Keyring 插件通常在服务器启动过程的早期加载,以便它们可用于可能依赖它们的内置插件和存储引擎。对于 keyring_file,请在服务器 my.cnf 文件中使用以下行,根据需要调整 .so 后缀

[mysqld]
early-plugin-load=keyring_file.so

有关插件加载的更多信息,请参阅 安装和卸载插件

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS 表或使用 SHOW PLUGINS 语句(参见 获取服务器插件信息)。例如

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE 'keyring%';
+--------------+---------------+
| PLUGIN_NAME  | PLUGIN_STATUS |
+--------------+---------------+
| keyring_file | ACTIVE        |
+--------------+---------------+

keyring_file 插件已安装时,它会公开一个系统变量,该变量指示它用于安全信息存储的数据文件的位置

mysql> SHOW VARIABLES LIKE 'keyring_file%';
+-------------------+----------------------------------+
| Variable_name     | Value                            |
+-------------------+----------------------------------+
| keyring_file_data | /usr/local/mysql/keyring/keyring |
+-------------------+----------------------------------+

要在测试后禁用插件,请在没有命名该插件的 --early-plugin-load 选项的情况下重新启动服务器。