MySQL 8.4.1
Source Code Documentation
"How to write a new keyring component"

Common keyring implementation infrastructure provides useful parts to minimize efforts involved in writing a new component.

This page will provide details about how a new keyring component can be implemented using the common infrastructure

Any keyring component can be divided in 3 parts:

  1. Configuration Management
  1. Service Implementation
  2. Backend Management

Configuration Management

A binary must be able to load a keyring component on top of minimal chassis. Hence, the component cannot use option management provided by underlying binary to read configuration for the keyring.

One way to read configuration is to accept it as a JSON file. A sample configuration file may look like following:

{
"version" : "1.0.0"
"config_key_1" : "config_data_1",
"config_key_2" : "config_data_2",
"config_key_3" : "config_data_3"
}

Various (key, value) pair would help component get details required to communicate with backend and initialize keyring.

You can use keyring_common::config::Config_reader to read a JSON file and extract value of individual configuration parameters.

Depending upon the services implemented by the component, it is possible that:

A> Configuration data can be queried at runtime

B> Configuration can be changed at runtime

Service Implementation

Please refer to Keyring Component for description of various services that a keyring component should implement. You may take a look at Keyring component services for details about specific services and various APIs.

If you are writing a keyring component that should work with MySQL server, the component must implement following services.

  1. Keyring reader service: s_mysql_keyring_reader_with_status Use keyring_common::service_definition::Keyring_reader_service_impl for service class declaration. Use KEYRING_READER_IMPLEMENTOR to add service implementation details required by component infrastructure.
  2. Keyring writer service: s_mysql_keyring_writer Use keyring_common::service_definition::Keyring_writer_service_impl for service class declaration. Use KEYRING_WRITER_IMPLEMENTOR to add service implementation details required by component infrastructure.
  3. Keyring generator service: s_mysql_keyring_generator Use keyring_common::service_definition::Keyring_generator_service_impl for service class declaration. Use KEYRING_GENERATOR_IMPLEMENTOR to add service implementation details required by component infrastructure.
  4. Keyring keys metadata iterator service: s_mysql_keyring_keys_metadata_iterator Use keyring_common::service_definition::Keyring_keys_metadata_iterator_service_impl for service class declaration. Use KEYRING_KEYS_METADATA_FORWARD_ITERATOR_IMPLEMENTOR to add service implementation details required by component infrastructure.
  5. Keyring component metadata query service: s_mysql_keyring_component_metadata_query Use keyring_common::service_definition::Keyring_metadata_query_service_impl for service class declaration. Use KEYRING_COMPONENT_METADATA_QUERY_IMPLEMENTOR to add service implementation details required by component infrastructure.
  6. Keyring load service: s_mysql_keyring_load Use keyring_common::service_definition::Keyring_load_service_impl for service class declaration. Use KEYRING_LOAD_IMPLEMENTOR to add service implementation details required by component infrastructure.
  7. Keyring AES service: s_mysql_keyring_aes Use keyring_common::service_definition::Keyring_aes_service_impl for service class declaration. Use KEYRING_AES_IMPLEMENTOR to add service implementation details required by component infrastructure.
  8. Keyring status service: s_mysql_keyring_component_status Use keyring_common::service_definition::Keyring_metadata_query_service_impl for service class declaration. Use KEYRING_COMPONENT_STATUS_IMPLEMENTOR to add service implementation details required by component infrastructure.

Please note that key of type AES and SECRET must be supported.

In addition, you will also need to implement log_builtins and log_builtins_string services if you are planning to use keyring common's implementation templates. The common keyring infrastrcture has a bare-minimum implementation of these services. You can use keyring_common::service_definition::Log_builtins_keyring for service class declaration. Use KEYRING_LOG_BUILTINS_IMPLEMENTOR and KEYRING_LOG_BUILTINS_STRING_IMPLEMENTOR to add service implementation details required by component infrastrcture.

Common keyring infrastructure also provides implementation for some of the above mentioned services. This will allow implementor to create a minimal definition of service APIs and use templates provided by common infra.

In order to do that, common keyring infrastrcture requires following:

  1. A handle to keyring_common::operations::Keyring_operations object This class provides a wrapper over keyring backend and expect that implementor provides handle to a backend class with set of APIs required to manage keys. Please see Backend Management for more details.
  2. A handle to keyring_common::service_implementation::Component_callbacks object This class provides callback methods which are implemented by individual component. For example: Keyring state, Maximum supported data length, metadata vector creation etc.

Assumping that above mentioned dependencies are satisfied, following are some inputs on how various services can be implemented.

  1. Keyring reader service: s_mysql_keyring_reader_with_status See keyring_common::service_implementation::init_reader_template See keyring_common::service_implementation::deinit_reader_template See keyring_common::service_implementation::fetch_length_template See keyring_common::service_implementation::fetch_template
  2. Keyring writer service: s_mysql_keyring_writer See keyring_common::service_implementation::store_template See keyring_common::service_implementation::remove_template
  3. Keyring generator service: s_mysql_keyring_generator See keyring_common::service_implementation::generate_template
  4. Keyring keys metadata iterator service: s_mysql_keyring_keys_metadata_iterator See keyring_common::service_implementation::init_keys_metadata_iterator_template See keyring_common::service_implementation::deinit_keys_metadata_iterator_template See keyring_common::service_implementation::keys_metadata_iterator_is_valid See keyring_common::service_implementation::keys_metadata_iterator_next See keyring_common::service_implementation::keys_metadata_get_length_template See keyring_common::service_implementation::keys_metadata_get_template
  5. Keyring component metadata query service: s_mysql_keyring_component_metadata_query See keyring_common::service_implementation::keyring_metadata_query_init_template See keyring_common::service_implementation::keyring_metadata_query_deinit_template See keyring_common::service_implementation::keyring_metadata_query_is_valid_template See keyring_common::service_implementation::keyring_metadata_query_next_template See keyring_common::service_implementation::keyring_metadata_query_get_length_template See keyring_common::service_implementation::keyring_metadata_query_get_template
  6. Keyring load service: s_mysql_keyring_load This service is specific to individual keyring component because it has strong dependency on component specific configuration details. The component should implement it as per its own requirement.
  7. Keyring AES service: s_mysql_keyring_aes See keyring_common::service_implementation::aes_get_encrypted_size_template See keyring_common::service_implementation::aes_encrypt_template See keyring_common::service_implementation::aes_decrypt_template
  8. Keyring status service: s_mysql_keyring_component_status See keyring_common::service_implementation::keyring_metadata_query_keyring_initialized_template

Backend Management

This part would be different for each keyring component. Backend can be a remote server, something that stored locally or a combination of both. Regardless of the backend, if keyring_common::operations::Keyring_operations is to be used, component must implement a class similar to following:

template <typename Data_extension>
class Backend {
public:
// Fetch data
// @param [in] metadata Key
// @param [out] data Value
// @returns Status of find operation
// @retval false Entry found. Check data.
// @retval true Entry missing.
bool get(const keyring_common::meta::Metadata &metadata,
// Store data
// @param [in] metadata Key
// @param [in, out] data Value
// @returns Status of store operation
// @retval false Entry stored successfully
// @retval true Failure
bool store(const keyring_common::meta::Metadata &metadata,
// Erase data located at given key
// @param [in] metadata Key
// @param [in] data Value - not used.
// @returns Status of erase operation
// @retval false Data deleted
// @retval true Could not find or delete data
bool erase(const keyring_common::meta::Metadata &metadata,
// Generate random data and store it
// @param [in] metadata Key
// @param [out] data Generated value
// @param [in] length Length of data to be generated
// @returns Status of generate + store operation
// @retval false Data generated and stored successfully
// @retval true Error
bool generate(const keyring_common::meta::Metadata &metadata,
// Populate cache
// @param [in] operations Handle to operations class
// @returns status of cache insertion
// @retval false Success
// @retval true Failure
bool load_cache(
// Maximum data length supported
size_t maximum_data_length() const;
// Get number of elements stored in backend
size_t size() const;
};
Sensitive data storage.
Definition: data.h:40
Common metadata.
Definition: meta.h:39
Keyring operations A class to perform operations on keyring.
Definition: operations.h:483
bool store(THD *thd, const Table *tp)
Stores the SDI for a table.
Definition: sdi.cc:607
operations
Definition: mysqlcheck.h:39
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
size_t size(const char *const c)
Definition: base64.h:46
void get(PSI_field *, PSI_longlong *) noexcept
Definition: pfs_plugin_column_bigint_v1_all_empty.cc:32

Common keyring infrastructure includes implementation that may help file management. It provides a content agnostic, backup aware file reader and writer.

Writer works in following manner:

  • Write content to backup file
  • If backup file exists, copy its content to main file
  • Remove backup file

Reader works in following manner:

  • Invoke writer to process backup file, if it exists
  • Read from main file

Please see keyring_common::data_file::File_writer for writer details and keyring_common::data_file::File_reader for reader details.

In-memory Data Management

Common keyring infrastructure also provides useful classes to manage data in memory.

  1. To cache metadata related to data, use keyring_common::meta::Metadata
  2. To cache data in memory, use keyring_common::data::Data
  3. To cache backend specific details for data (e.g. ID generated by backend), use keyring_common::data::Data_extension
  4. A reader/writer pair for JSON data that can be used to store data, related metadata and data extension if any. See keyring_common::json_data::Json_reader and keyring_common::json_data::Json_writer.

    Expected JSON format is specified below:

    {
    "version": "1.0",
    "elements": [
    {
    "user": "<user_name>",
    "data_id": "<name>",
    "data_type": "<data_type>",
    "data": "<hex_of_data>",
    "extension": [
    ]
    },
    ...
    ...
    ]
    }