MySQL Server utilizes keyring to store cryptographic keys used by several modules to secure data stored by them. For example, InnoDB storage engine uses a key to encrypt tablespace, binary log and relay log management use keys to encrypt passwords for the log files. There are several keyring components and plugins that may be used to generate, manage, encrypt/decrypt and store keys in different ways, depending how MySQL is deployed (cloud platform or on premises). OCI keyring component exploits Oracle Cloud Infrastructure Vault, HashiCorp keyring component communicates with HashiCorp Vault for key storage, keyring encrypted file component stores keys in a local, encrypted file and so on.
MySQL AWS keyring component may be of interest for users running MySQL server on AWS container or compute node. The component utilizes Amazon Web Services Key Management Service (AWS KMS) as a back end for key generation and encryption and utilizes a file as a key storage. This component was introduced in MySQL Enterprise Edition version 9.2 in order to replace the AWS Keyring Plugin. Components are more independent and better encapsulated (thus more secure) extensions to MySQL compared to plugins in general. Further motivation for moving from keyring plugins to components can be found in this article.
By way of the moving process, we decided to enrich the component’s functionality. The plugin uses long term AWS secret access key as the only authentication method. Long term credentials are not very safe and it is not a method recommended by AWS. This method is still available in the component (simple authentication mode), but it adds a possibility to use the standard AWS configuration mechanism with authentication based on AWS default credentials provider chain (native authentication mode). The credentials provider chain may use several credential sources: files, environment variables, external services and other. That mode also allows for leveraging role connected to AWS container or compute node to improve security and provides more configuration parameters related to AWS connection (e.g. timeouts, proxying, CA). Finally, the native mode uses standard AWS SDK configuration mechanisms, so it works exactly as for any other AWS client.
The component also introduces the option to cache the MySQL keys in the memory encrypted (safer, probability of viewing keys in a memory dump is much smaller) or unencrypted (quicker, the keys don’t have to be unencrypted on each usage). The plugin always keeps the keys encrypted in the cache.
Configuration
Same as other keyring components, component_keyring_aws must be loaded by the MySQL server at an early stage of its startup. Because of that, keyring components are not installed with INSTALL COMPONENT statement. Instead, the server reads a manifest file to decide which component should be loaded and the component reads from its own configuration file. In practice it means, that for any changes to the keyring configuration to take effect, the MySQL server must be restarted or a special command ALTER INSTANCE RELOAD KEYRING must be used.
At first the server reads the global manifest file which must be located in the directory where the server is installed. The manifest file must be named mysqld.my, be in JSON format and contain:
{
"components": "file://component_keyring_aws"
}
In case different components are needed for different database instances, local manifest files with the above content should be placed in the data directories. The global manifest must then contain:
{
"read_local_manifest": true
}
The component’s configuration file is also in JSON format and must be named component_keyring_aws.cnf. The server reads the global configuration from the server plugin directory first. It may contain the configuration settings, for example:
{
"cmk_id": "arn:aws:kms:us-east-1:79566666666:key/d0111111-1111-1111-1111-999999999abd",
"data_file": "/usr/local/mysql/keyring.json",
"cache_keys": true,
"read_only": false,
"aws_authentication":
{
...
},
"aws_connection":
{
...
}
}
or indicate using local configuration files (located in the data directories):
{
"read_local_config": true
}
The general configuration parameters are as follows:
cmk_id: identifier of Customer Master Key. CMK is a key used by AWS for cryptographic operations on customer data and it must be created in AWS KMS. See AWS documentation on how to do it.data_file: path to JSON file where MySQL keys used by the component are stored.cache_keys: if set to true, the keys are cached in the memory in plain text, if set to false the keys are decrypted when accessed.read_only: when true, no operations which modify the keyring are allowed.aws_connection: an optional object that may contain connection related settings like proxy or connection timeout. Look at MySQL documentation for details.
Simple authentication mode
In this mode, AWS credentials are stored directly in component_keyring_aws.cnf. The aws_authentication object in this case looks like:
"aws_authentication":
{
"mode": "simple",
"region": "us-east-1",
"access_key_id": "wwwwwwwwwwwwwEXAMPLE",
"access_key_secret": "xxxxxxxxxxxxx/yyyyyyy/zzzzzzzzEXAMPLEKEY"
}
Native authentication mode
In this mode, the component uses the standard AWS authentication configuration mechanism. The aws_authentication object may look like:
"aws_authentication":
{
"mode": "native",
"profile": "mysql-profile"
}
The optional profile parameter denotes an AWS configuration profile which is used as a section name in the AWS config file (see AWS SDKs and Tools: Configuration: Shared config and credentials files).
The authentication in native mode is based on AWS default credentials provider chain. It consists of so called credential providers. Each credential provider provides credentials taken from some source. The chain calls the providers until the credentials are collected for further use. The default credential provider chain consists of the following items:
-
EnvironmentAWSCredentialsProvider -provides AWS access keys taken from environment variables (see AWS access keys). This is convenient in a temporary or development scenario but not recommended for production.
-
ProfileConfigFileAWSCredentialsProvider – provides AWS access keys taken from
credentialsfile, sectiondefault(see AWS access keys). This is recommended for MySQL server running out of AWS. -
ProcessCredentialsProvider – provides AWS access keys taken from output of an external command run, the command is specified by the
credential_processparameter from the AWSconfig, the output must be a valid JSON object (see Process credential provider). -
STSAssumeRoleWebIdentityCredentialsProvider – provides a set of temporary security credentials of a specific role (see Assume role credential provider).
-
SSOCredentialsProvider – provides credentials from the AWS IAM Identity Center (see IAM Identity Center credential provider).
-
TaskRoleCredentialsProvider – provides credentials to be used inside an AWS ECS container (see Amazon ECS task role). This is recommended when MySQL server runs on an AWS ECS container.
-
InstanceProfileCredentialsProvider – provides credentials loaded from the Amazon EC2 Instance Metadata Service (IMDS) (see IMDS credential provider). This is recommended when MySQL server runs on an AWS EC2 node.
AWS client configuration is very flexible and allows for fine tuning, but it is a broad topic that goes beyond the scope of this article. Please consult AWS SDKs and Tools: Configuration for details.
Migrating from the plugin
Here we describe migration from the AWS keyring plugin to the component, but note please, that it is also possible to migrate the keyring data (keys) from another plugin or component.
The keyring data may be migrated using the MySQL server run in the keyring migration mode. As the first step the AWS keyring component must be properly configured (there is no automated way to migrate the configuration). The configuration may be translated as follows:
- For the component’s
cmk_iduse plugin’skeyring_aws_cmk_id. - For the component’s
regionuse plugin’skeyring_aws_region. - Both the plugin and the component store the keys in a file, but they use different formats, so it should be ensured that both configs don’t point to the same file. So, the component’s
data_fileshould differ from the plugin’skeyring_aws_data_file. - Plugin’s
keyring_aws_conf_filepoints to a file that contains the secret access key ID and the key itself.- For simple authentication mode they should be set as values of
access_key_idandaccess_key_secretin the component’s configuration file. - For native authentication mode they may be set in the AWS
configorcredentialsfile (see AWS access keys) if no other authentication method will be used.
- For simple authentication mode they should be set as values of
The keyring data migration was described in Introducing Keyring Components in MySQL post, see also MySQL documentation for more details. In the simplest case of offline migration, the server must be stopped and then started with the following parameters:
--keyring-migration-to-component
--keyring-migration-source=keyring_aws.so
--keyring-migration-destination=component_keyring_aws.so
--keyring_aws_cmk_id=...
--keyring_aws_conf_file=...
--keyring_aws_data_file=..
Set keyring_aws_* options to whatever was used by the plugin.
Once the migration is done, the plugin specific variables should be removed from the configuration of the server and it may be started normally.
Conclusion
MySQL provides several keyring components and plugins useful in different cloud (like OCI, Azure or AWS) or on premises deployments. Components are more independent and better encapsulated (thus more secure) extensions to MySQL compared to plugins in general, so plugins are gradually replaced by components. AWS keyring component provides additional features compared to AWS keyring plugin. The component enables configuration that is compatible with other AWS client tools, more flexible and may be more appropriate while running in an AWS ECS container or an EC2 node. Finally, a simple way to migrate the keys from the plugin to the component is in place.
The new functionality of the MySQL AWS keyring component can be found in MySQL Enterprise Edition 9.2. Another reason to upgrade to Enterprise!
