366 lines
13 KiB
C++
366 lines
13 KiB
C++
/* Copyright (c) 2016, 2024, Oracle and/or its affiliates.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is designed to work with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have either included with
|
|
the program or referenced in the documentation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#ifndef PERSISTED_VARIABLE_H_INCLUDED
|
|
#define PERSISTED_VARIABLE_H_INCLUDED
|
|
|
|
#include <stddef.h>
|
|
#include <map>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
#include "map_helpers.h"
|
|
#include "my_alloc.h"
|
|
#include "my_inttypes.h"
|
|
#include "my_psi_config.h"
|
|
#include "mysql/components/services/bits/mysql_mutex_bits.h"
|
|
#include "mysql/components/services/bits/psi_bits.h"
|
|
#include "mysql/psi/mysql_mutex.h"
|
|
#include "sql/psi_memory_key.h"
|
|
#include "sql_string.h"
|
|
|
|
class Json_dom;
|
|
class Json_object;
|
|
class THD;
|
|
class set_var;
|
|
class sys_var;
|
|
struct MYSQL_FILE;
|
|
|
|
/**
|
|
STRUCT st_persist_var
|
|
|
|
This structure represents information of a variable which is to
|
|
be persisted in mysql-auto.cnf file.
|
|
*/
|
|
struct st_persist_var final {
|
|
std::string key;
|
|
std::string value;
|
|
ulonglong timestamp;
|
|
std::string user;
|
|
std::string host;
|
|
bool is_null;
|
|
st_persist_var();
|
|
st_persist_var(THD *thd);
|
|
st_persist_var(const std::string key, const std::string value,
|
|
const ulonglong timestamp, const std::string user,
|
|
const std::string host, const bool is_null);
|
|
/* This is custom comparison function used to make the unordered_set
|
|
work with the default std::hash for user defined types. */
|
|
bool operator==(const st_persist_var &persist_var) const {
|
|
return key == persist_var.key;
|
|
}
|
|
};
|
|
|
|
/**
|
|
STRUCT st_persist_var_hash
|
|
|
|
This structure has a custom hasher function used to make the unordered_set
|
|
to work with the default std::hash for user defined types.
|
|
*/
|
|
struct st_persist_var_hash {
|
|
size_t operator()(const st_persist_var &pv) const { return pv.key.length(); }
|
|
};
|
|
|
|
/**
|
|
CLASS Persisted_variables_cache
|
|
Holds <name,value> pair of all options which needs to be persisted
|
|
to a file.
|
|
|
|
OVERVIEW
|
|
--------
|
|
When first SET PERSIST statement is executed we instantiate
|
|
Persisted_variables_cache which loads the config file if present into
|
|
m_persisted_dynamic_variables set. This is a singleton operation.
|
|
m_persisted_dynamic_variables is an in-memory copy of config file itself. If
|
|
the SET statement passes then this in-memory is updated and flushed to file as
|
|
an atomic operation.
|
|
|
|
Next SET PERSIST statement would only update the in-memory copy and sync
|
|
to config file instead of loading the file again.
|
|
*/
|
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
|
void my_init_persist_psi_keys(void);
|
|
#endif /* HAVE_PSI_INTERFACE */
|
|
|
|
using Persisted_variables_umap =
|
|
malloc_unordered_map<std::string, st_persist_var>;
|
|
using Persisted_variables_uset =
|
|
malloc_unordered_set<st_persist_var, st_persist_var_hash>;
|
|
|
|
class Persisted_variables_cache final {
|
|
protected:
|
|
enum class File_version {
|
|
VERSION_V1 = 1,
|
|
VERSION_V2,
|
|
};
|
|
|
|
public:
|
|
explicit Persisted_variables_cache();
|
|
int init(int *argc, char ***argv);
|
|
static Persisted_variables_cache *get_instance();
|
|
/**
|
|
Update in-memory copy for every SET PERSIST statement
|
|
*/
|
|
bool set_variable(THD *thd, set_var *system_var);
|
|
/**
|
|
Driver: Flush in-memory copy to persistent file
|
|
*/
|
|
bool flush_to_file();
|
|
/**
|
|
Write v2 persistent file
|
|
*/
|
|
bool write_persist_file_v2(String &dest, bool &do_cleanup);
|
|
/**
|
|
Driver function: Read options from persistent file
|
|
*/
|
|
int read_persist_file();
|
|
/**
|
|
Read v1 persistent file
|
|
*/
|
|
int read_persist_file_v1(const Json_object *json_object);
|
|
/**
|
|
Read v2 persistent file
|
|
*/
|
|
int read_persist_file_v2(const Json_object *json_object);
|
|
/**
|
|
Search for persisted config file and if found read persistent options
|
|
*/
|
|
bool load_persist_file();
|
|
bool set_persisted_options(bool plugin_options,
|
|
const char *target_var_name = nullptr,
|
|
int target_var_name_length = 0);
|
|
/**
|
|
Reset persisted options
|
|
*/
|
|
bool reset_persisted_variables(THD *thd, const char *name, bool if_exists);
|
|
|
|
/**
|
|
Get persisted variables
|
|
*/
|
|
Persisted_variables_uset *get_persisted_dynamic_variables();
|
|
/**
|
|
Get persisted parse-early variables
|
|
*/
|
|
Persisted_variables_uset *get_persisted_dynamic_parse_early_variables();
|
|
/**
|
|
Get SENSITIVE persisted variables
|
|
*/
|
|
Persisted_variables_uset *get_persisted_dynamic_sensitive_variables(THD *thd);
|
|
|
|
/**
|
|
Get persisted static variables
|
|
*/
|
|
Persisted_variables_umap *get_persisted_static_variables();
|
|
/**
|
|
Get persisted parse-early static variables
|
|
*/
|
|
Persisted_variables_umap *get_persisted_static_parse_early_variables();
|
|
/**
|
|
Get SENSITIVE persisted static variables
|
|
*/
|
|
Persisted_variables_umap *get_persisted_static_sensitive_variables(THD *thd);
|
|
|
|
/**
|
|
append read only persisted variables to command line options with a
|
|
separator.
|
|
*/
|
|
bool append_read_only_variables(int *argc, char ***argv,
|
|
bool arg_separator_added = false,
|
|
bool plugin_options = false,
|
|
MEM_ROOT *root_to_use = nullptr);
|
|
|
|
/**
|
|
append PARSE EARLY read only persisted variables to command
|
|
line options with a separator.
|
|
*/
|
|
bool append_parse_early_variables(int *argc, char ***argv,
|
|
bool &arg_separator_added);
|
|
|
|
void cleanup();
|
|
|
|
/**
|
|
Acquire lock on m_persisted_dynamic_variables/m_persisted_static_variables
|
|
*/
|
|
void lock() { mysql_mutex_lock(&m_LOCK_persist_variables); }
|
|
/**
|
|
Release lock on m_persisted_dynamic_variables/m_persisted_static_variables
|
|
*/
|
|
void unlock() { mysql_mutex_unlock(&m_LOCK_persist_variables); }
|
|
/**
|
|
Assert caller that owns lock on
|
|
m_persisted_dynamic_variables/m_persisted_static_variables
|
|
*/
|
|
void assert_lock_owner() {
|
|
mysql_mutex_assert_owner(&m_LOCK_persist_variables);
|
|
}
|
|
/**
|
|
Set internal state to reflect keyring support status
|
|
*/
|
|
void keyring_support_available();
|
|
|
|
std::string to_hex(const std::string &value);
|
|
std::string from_hex(const std::string &value);
|
|
|
|
private:
|
|
/* Helper function to get variable value */
|
|
static String *get_variable_value(THD *thd, sys_var *system_var, String *str,
|
|
bool *is_null);
|
|
/**
|
|
If the variable has an alias, return the name for the alias.
|
|
*/
|
|
static const char *get_variable_alias(const sys_var *system_var);
|
|
static std::string get_variable_alias(const char *name);
|
|
/* Helper function to extract variables from json formatted string */
|
|
bool extract_variables_from_json(const Json_dom *dom,
|
|
bool is_read_only = false);
|
|
/**
|
|
After extracting the variables from the JSON, we duplicate any
|
|
variable definition that relates to an alias.
|
|
*/
|
|
void load_aliases();
|
|
|
|
enum class return_status { NOT_REQUIRED, SUCCESS, ERROR };
|
|
bool get_file_encryption_key(std::unique_ptr<unsigned char[]> &file_key,
|
|
size_t &file_key_length, bool generate = false);
|
|
return_status encrypt_sensitive_variables();
|
|
return_status decrypt_sensitive_variables();
|
|
|
|
/** Helper to set source information for PARSE_EARLY variables */
|
|
void set_parse_early_sources();
|
|
|
|
/** Helper function to handle changes in option type */
|
|
void handle_option_type_change();
|
|
|
|
private:
|
|
/* Helper functions for file IO */
|
|
void clear_sensitive_blob_and_iv();
|
|
bool open_persist_file(int flag);
|
|
bool open_persist_backup_file(int flag);
|
|
void close_persist_file();
|
|
|
|
private:
|
|
/*
|
|
There are two main types of variables:
|
|
1. Static variables: Those which cannot be set at runtime
|
|
2. Dynamic variables: Those which can be set on a running server
|
|
|
|
Each of these types is further divided in 3 sub-types:
|
|
A. PARSE_EARLY variables - This set of variables require to be set very
|
|
early in server start-up sequence
|
|
B. SENSITIVE variables - This set of variables may be stored in
|
|
encrypted format if a suitable keyring
|
|
component is available
|
|
C. All other variables - These are the variables that do not have
|
|
none of the mentioned properties
|
|
|
|
Two of the above mentioned sub-types exist because we treat
|
|
variables with certain properties in special manner for reasons mentioned
|
|
above for each of the In future, more categories may need special
|
|
treatment and if so, above mentioned sub-categories will increase.
|
|
|
|
These gives us total of 6 categories (3 each for static and dynamic
|
|
types of variables). Each of these categories of variables are processed
|
|
and/or loaded at different point of time in start-up sequence:
|
|
|
|
- 1A and 2A variables are added to command line argument at the very
|
|
beginning of the start-up
|
|
- 1B and 2B are decrypted once keyring component is loaded.
|
|
- 1B and 1C are added to command line
|
|
- 2B and 2C are set at a later point in start-up cycle when THD
|
|
initialization is possible. Some of the variables of types 2B and 2C
|
|
are not processed until corresponding component or plugin is loaded.
|
|
These subsets of variables are moved to special in-memory containers
|
|
reserved for them.
|
|
|
|
The persisted options file contains 6 JSON objects - one each for
|
|
above mentioned categories. When file is read, data from each JSON object
|
|
is loaded in different in-memory containers.
|
|
*/
|
|
|
|
/* In memory copy of Persisted PARSE EARLY static variables' values */
|
|
Persisted_variables_umap m_persisted_static_sensitive_variables;
|
|
/* In memory copy of Persisted SENSITIVE static variables' values */
|
|
Persisted_variables_umap m_persisted_static_parse_early_variables;
|
|
/* In memory copy of all other Persisted static variables' values */
|
|
Persisted_variables_umap m_persisted_static_variables;
|
|
|
|
/* In memory copy of Persisted PARSE EARLY dynamic variables' values */
|
|
Persisted_variables_uset m_persisted_dynamic_parse_early_variables;
|
|
/* In memory copy of Persisted SENSITIVE dynamic variables' values */
|
|
Persisted_variables_uset m_persisted_dynamic_sensitive_variables;
|
|
/* In memory copy of all other Persisted dynamic variables' values */
|
|
Persisted_variables_uset m_persisted_dynamic_variables;
|
|
|
|
/*
|
|
In memory copy of Persisted SENSITIVE dynamic
|
|
variables whose plugin is not yet installed
|
|
*/
|
|
Persisted_variables_uset m_persisted_dynamic_sensitive_plugin_variables;
|
|
/*
|
|
In memory copy of all other Persisted dynamic
|
|
variables whose plugin is not yet installed
|
|
*/
|
|
Persisted_variables_uset m_persisted_dynamic_plugin_variables;
|
|
|
|
struct Key_info {
|
|
std::string m_master_key_name{"persisted_variables_key"};
|
|
std::string m_master_key_type{"AES"};
|
|
const size_t m_master_key_size{32};
|
|
|
|
std::string m_file_key{};
|
|
std::string m_file_key_iv{};
|
|
};
|
|
|
|
/* Key */
|
|
Key_info m_key_info;
|
|
|
|
/* Status of keyring support */
|
|
bool m_keyring_support_available{false};
|
|
/* Sensitive variables blob - HEX representation */
|
|
std::string m_sensitive_variables_blob{};
|
|
/* IV - HEX representation */
|
|
std::string m_iv{};
|
|
|
|
mysql_mutex_t m_LOCK_persist_variables;
|
|
static Persisted_variables_cache *m_instance;
|
|
|
|
/* File handler members */
|
|
MYSQL_FILE *m_fd;
|
|
std::string m_persist_filename;
|
|
std::string m_persist_backup_filename;
|
|
mysql_mutex_t m_LOCK_persist_file;
|
|
/* Memory for parse early read only persisted options */
|
|
MEM_ROOT parse_early_persisted_argv_alloc{
|
|
key_memory_persisted_variables_memroot, 512};
|
|
/* Memory for read only persisted options */
|
|
MEM_ROOT ro_persisted_argv_alloc{key_memory_persisted_variables_memroot, 512};
|
|
/* Memory for read only persisted plugin options */
|
|
MEM_ROOT ro_persisted_plugin_argv_alloc{
|
|
key_memory_persisted_variables_memroot, 512};
|
|
|
|
/* default version */
|
|
File_version m_default_version = File_version::VERSION_V2;
|
|
};
|
|
|
|
#endif /* PERSISTED_VARIABLE_H_INCLUDED */
|