Extending MySQL 9.3  /  ...  /  Writing Keyring Plugins

4.4.12 Writing Keyring Plugins

MySQL Server supports a keyring service that enables internal server components and plugins to securely store sensitive information for later retrieval. This section describes how to write a server-side keyring plugin that can be used by service functions to perform key-management operations. For general keyring information, see The MySQL Keyring.

Important

MySQL 8.4 removed the deprecated keyring plugins in favor of using the keyring components. For example, use component_keyring_file instead of keyring_file. For related information, see Keyring Components Versus Keyring Plugins.

The instructions here are based on the source code in the plugin/keyring directory of MySQL source distributions. The source files in that directory implement a plugin named keyring_file that uses a file local to the server host for data storage.

To write a keyring plugin, include the following header file in the plugin source file. Other MySQL or general header files might also be needed, depending on the plugin capabilities and requirements.

#include <mysql/plugin_keyring.h>

plugin_keyring.h includes plugin.h, so you need not include the latter file explicitly. plugin.h defines the MYSQL_KEYRING_PLUGIN server plugin type and the data structures needed to declare the plugin. plugin_keyring.h defines data structures specific to keyring plugins.

A keyring plugin, like any MySQL server plugin, has a general plugin descriptor (see Section 4.4.2.1, β€œServer Plugin Library and Plugin Descriptors”). In keyring.cc, the general descriptor for keyring_file looks like this:

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;

The name member (keyring_file) indicates the plugin name. This is the name displayed by INFORMATION_SCHEMA.PLUGINS or SHOW PLUGINS.

The general descriptor also refers to keyring_system_variables, a structure that exposes a system variable to the SHOW VARIABLES statement:

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

The keyring_init initialization function creates the data file if it does not exist, then reads it and initializes the keystore. The keyring_deinit function frees data structures associated with the file.

The keyring_descriptor value in the general descriptor points to the type-specific descriptor. For keyring plugins, this descriptor has the following structure:

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);
};

The type-specific descriptor has these members:

  • interface_version: By convention, type-specific plugin descriptors begin with the interface version for the given plugin type. The server checks interface_version when it loads the plugin to see whether the plugin is compatible with it. For keyring plugins, the value of the interface_version member is MYSQL_KEYRING_INTERFACE_VERSION (defined in plugin_keyring.h).

  • mysql_key_store: A function that obfuscates and stores a key in the keyring.

  • mysql_key_fetch: A function that deobfuscates and retrieves a key from the keyring.

  • mysql_key_remove: A function that removes a key from the keyring.

  • mysql_key_generate: A function that generates a new random key and stores it in the keyring.

For the keyring_file plugin, the type-specific descriptor looks like this:

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

The mysql_key_xxx functions implemented by a keyring plugin are analogous to the my_key_xxx functions exposed by the keyring service API. For example, the mysql_key_store plugin function is analogous to the my_key_store keyring service function. For information about the arguments to keyring service functions and how they are used, see The Keyring Service.

To compile and install a plugin library file, use the instructions in Section 4.4.3, β€œCompiling and Installing Plugin Libraries”. To make the library file available for use, install it in the plugin directory (the directory named by the plugin_dir system variable). For the keyring_file plugin, it is compiled and installed when you build MySQL from source. It is also included in binary distributions. The build process produces a shared object library with a name of keyring_file.so (the .so suffix might differ depending on your platform).

Keyring plugins typically are loaded early during the server startup process so that they are available to built-in plugins and storage engines that might depend on them. For keyring_file, use these lines in the server my.cnf file, adjusting the .so suffix for your platform as necessary:

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

For additional information about plugin loading, see Installing and Uninstalling Plugins.

To verify plugin installation, examine the INFORMATION_SCHEMA.PLUGINS table or use the SHOW PLUGINS statement (see Obtaining Server Plugin Information). For example:

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

While the keyring_file plugin is installed, it exposes a system variable that indicates the location of the data file it uses for secure information storage:

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

To disable the plugin after testing it, restart the server without an --early-plugin-load option that names the plugin.