Commit 46089d76 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-9659 : AWS KMS encryption plugin

parent 517584dd
# We build parts of AWS C++ SDK as CMake external project
# The restrictions of the SDK (https://github.com/awslabs/aws-sdk-cpp/blob/master/README.md)
# are
# - OS : Windows,Linux or OSX
# - C++11 compiler : VS2013+, gcc 4.7+, clang 3.3+
# - libcurl development package needs to be present on Unixes
#
# If we build SDK outselves, we'll need require GIT to be present on the build machine
# Give message why the building this plugin is skipped (only if -DVERBOSE is defined)
# or if plugin is explicitely requested to build. Then bail out.
MACRO(SKIP_AWS_PLUGIN msg)
IF(VERBOSE OR "${PLUGIN_AWS_KEY_MANAGEMENT}" MATCHES "^(STATIC|DYNAMIC)$")
MESSAGE(STATUS "Skip aws_key_management - ${msg}")
ENDIF()
RETURN()
ENDMACRO()
# This plugin needs recent C++ compilers (AWS C++ SDK header files are using C++11 features)
SET(CXX11_FLAGS)
SET(OLD_COMPILER_MSG "AWS SDK requires c++11 -capable compiler (minimal supported versions are g++ 4.7, clang 3.3, VS2103)")
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
IF (GCC_VERSION VERSION_LESS 4.8)
SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}")
ENDIF()
SET(CXX11_FLAGS "-std=c++11")
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
IF ((CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3) OR
(CLANG_VERSION_STRING AND CLANG_VERSION_STRING VERSION_LESS 3.3))
SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}")
ENDIF()
SET(CXX11_FLAGS "-stdlib=libc++")
ELSEIF(MSVC)
IF (MSVC_VERSION LESS 1800)
SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}")
ENDIF()
ELSE()
SKIP_AWS_PLUGIN("Compiler not supported by AWS C++ SDK")
ENDIF()
IF (NOT(WIN32 OR APPLE OR (CMAKE_SYSTEM_NAME MATCHES "Linux")))
SKIP_AWS_PLUGIN("OS unsupported by AWS SDK")
ENDIF()
# Figure out where AWS installs SDK libraries
# The below is defined in AWS SDK's CMakeLists.txt
# (and their handling is weird, every OS has special install directory)
IF(WIN32)
SET(SDK_INSTALL_BINARY_PREFIX "windows")
ELSEIF(APPLE)
SET(SDK_INSTALL_BINARY_PREFIX "mac")
ELSEIF(UNIX)
SET(SDK_INSTALL_BINARY_PREFIX "linux")
ENDIF()
IF(NOT APPLE)
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/intel64")
ELSE()
SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/ia32")
ENDIF()
ENDIF()
IF(CMAKE_CONFIGURATION_TYPES)
SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/${CMAKE_CFG_INTDIR}")
ENDIF()
FIND_LIBRARY(AWS_CPP_SDK_CORE NAMES aws-cpp-sdk-core PATH_SUFFIXES "${SDK_INSTALL_BINARY_PREFIX}")
FIND_LIBRARY(AWS_CPP_SDK_KMS NAMES aws-cpp-sdk-core PATH_SUFFIXES "${SDK_INSTALL_BINARY_PREFIX}")
SET(CMAKE_REQUIRED_FLAGS ${CXX11_FLAGS})
CHECK_INCLUDE_FILE_CXX(aws/kms/KMSClient.h HAVE_AWS_HEADERS)
IF(AWS_CPP_SDK_CORE AND AWS_CPP_SDK_KMS AND HAVE_AWS_HEADERS)
# AWS C++ SDK installed
SET(AWS_SDK_LIBS ${AWS_CPP_SDK_CORE} ${AWS_CPP_SDK_KMS})
ELSE()
# Build from source, using ExternalProject_Add
IF(CMAKE_VERSION VERSION_LESS "2.8.8")
SKIP_AWS_PLUGIN("CMake is too old")
ENDIF()
FIND_PACKAGE(Git)
IF(NOT GIT_FOUND)
SKIP_AWS_PLUGIN("no GIT")
ENDIF()
INCLUDE(ExternalProject)
IF(UNIX)
FIND_PACKAGE(CURL)
IF(NOT CURL_FOUND)
SKIP_AWS_PLUGIN("AWS C++ SDK requires libcurl development package")
ENDIF()
SET(PIC_FLAG -fPIC)
ENDIF()
IF(MSVC)
SET(EXTRA_SDK_CMAKE_FLAGS -DCMAKE_CXX_FLAGS_DEBUGOPT="" -DCMAKE_EXE_LINKER_FLAGS_DEBUGOPT="" -DCMAKE_CXX_FLAGS=/wd4592)
ENDIF()
IF(CMAKE_CXX_COMPILER)
SET(EXTRA_SDK_CMAKE_FLAGS ${EXTRA_SDK_CMAKE_FLAGS} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
ENDIF()
# Relax AWS C++ SDK unreasonably high requirements for CMake version. Use replace utility (from MariaDB build)
# to patch their CMakeLists.txt
SET(AWS_SDK_PATCH_COMMAND )
ExternalProject_Add(
aws_sdk_cpp
GIT_REPOSITORY "https://github.com/awslabs/aws-sdk-cpp.git"
GIT_TAG "0.9.6" # single tag
UPDATE_COMMAND ""
PATCH_COMMAND replace 3.1.2 2.8 -- ${CMAKE_BINARY_DIR}/aws-sdk-cpp/CMakeLists.txt
SOURCE_DIR "${CMAKE_BINARY_DIR}/aws-sdk-cpp"
CMAKE_ARGS
-DBUILD_ONLY=aws-cpp-sdk-kms -DSTATIC_LINKING=1
"-DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} ${PIC_FLAG}"
"-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${PIC_FLAG}"
"-DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} ${PIC_FLAG}"
"-DCMAKE_CXX_FLAGS_MINSIZEREL=${CMAKE_CXX_FLAGS_MINSIZEREL} ${PIC_FLAG}"
${EXTRA_SDK_CMAKE_FLAGS}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/aws_sdk_cpp
TEST_COMMAND ""
)
# We do not need to build the whole SDK , just 2 of its libs
set(AWS_SDK_LIBS aws-cpp-sdk-core aws-cpp-sdk-kms)
FOREACH(lib ${AWS_SDK_LIBS})
ADD_LIBRARY(${lib} STATIC IMPORTED GLOBAL)
ADD_DEPENDENCIES(${lib} aws_sdk_cpp)
SET(loc "${CMAKE_BINARY_DIR}/aws_sdk_cpp/lib/${SDK_INSTALL_BINARY_PREFIX}/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX}")
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION ${loc})
IF(WIN32)
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "bcrypt;winhttp;wininet;userenv")
ELSE()
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "${SSL_LIBRARIES};${CURL_LIBRARIES}")
ENDIF()
ENDFOREACH()
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
# Need whole-archive , otherwise static libraries are not linked
SET(AWS_SDK_LIBS -Wl,--whole-archive ${AWS_SDK_LIBS} -Wl,--no-whole-archive)
ENDIF()
SET_TARGET_PROPERTIES(aws_sdk_cpp PROPERTIES EXCLUDE_FROM_ALL TRUE)
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/aws_sdk_cpp/include)
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_FLAGS}")
MYSQL_ADD_PLUGIN(aws_key_management aws_key_management_plugin.cc
COMPONENT aws-key-management
LINK_LIBRARIES ${AWS_SDK_LIBS}
DISABLED)
/*
Copyright (c) 2016 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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 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 */
#include <my_global.h>
#include <my_pthread.h>
#include <my_sys.h>
#include <my_dir.h>
#include <mysql/plugin_encryption.h>
#include <my_crypt.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <mysqld_error.h>
#include <base64.h>
#include <map>
#include <algorithm>
#include <string>
#include <vector>
#include <iterator>
#include <sstream>
#include <fstream>
#include <aws/core/client/AWSError.h>
#include <aws/core/utils/logging/AWSLogging.h>
#include <aws/core/utils/logging/ConsoleLogSystem.h>
#include <aws/kms/KMSClient.h>
#include <aws/kms/model/DecryptRequest.h>
#include <aws/kms/model/DecryptResult.h>
#include <aws/kms/model/GenerateDataKeyWithoutPlaintextRequest.h>
#include <aws/kms/model/GenerateDataKeyWithoutPlaintextResult.h>
#include <aws/core/utils/Outcome.h>
using namespace std;
using namespace Aws::KMS;
using namespace Aws::KMS::Model;
using namespace Aws::Utils::Logging;
extern void sql_print_error(const char *format, ...);
extern void sql_print_warning(const char *format, ...);
extern void sql_print_information(const char *format, ...);
/* Plaintext key info struct */
struct KEY_INFO
{
unsigned int key_id;
unsigned int key_version;
unsigned int length;
unsigned char data[MY_AES_MAX_KEY_LENGTH];
bool load_failed; /* if true, do not attempt to reload?*/
public:
KEY_INFO() : key_id(0), key_version(0), length(0), load_failed(false){};
};
#define KEY_ID_AND_VERSION(key_id,version) ((longlong)key_id << 32 | version)
/* Cache for the latest version, per key id */
static std::map<uint, uint> latest_version_cache;
/* Cache for plaintext keys */
static std::map<ulonglong, KEY_INFO> key_info_cache;
static const char *key_spec_names[]={ "AES_128", "AES_256", 0 };
/* Plugin variables */
static char* master_key_id;
static unsigned long key_spec;
static unsigned long log_level;
static int rotate_key;
/* AWS functionality*/
static int aws_decrypt_key(const char *path, KEY_INFO *info);
static int aws_generate_datakey(uint key_id, uint version);
static int extract_id_and_version(const char *name, uint *id, uint *ver);
static unsigned int get_latest_key_version(unsigned int key_id);
static unsigned int get_latest_key_version_nolock(unsigned int key_id);
static int load_key(KEY_INFO *info);
/* Mutex to serialize access to caches */
static mysql_mutex_t mtx;
#ifdef HAVE_PSI_INTERFACE
static uint mtx_key;
static PSI_mutex_info mtx_info = {&mtx_key, "mtx", 0};
#endif
static Aws::KMS::KMSClient *client;
/* Redirect AWS trace to error log */
class MySQLLogSystem : public Aws::Utils::Logging::FormattedLogSystem
{
public:
using Base = FormattedLogSystem;
MySQLLogSystem(LogLevel logLevel) :
Base(logLevel)
{
}
virtual LogLevel GetLogLevel(void) const override
{
return (LogLevel)log_level;
}
virtual ~MySQLLogSystem()
{
}
protected:
virtual void ProcessFormattedStatement(Aws::String&& statement) override
{
#ifdef _WIN32
/*
On Windows, we can't use C runtime functions to write to stdout,
because we compile with static C runtime, so plugin has a stdout
different from server. Thus we're using WriteFile().
*/
DWORD nSize= (DWORD)statement.size();
DWORD nWritten;
const char *s= statement.c_str();
HANDLE h= GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(h, s, nSize, &nWritten, NULL);
#else
printf("%s", statement.c_str());
#endif
}
};
/*
Plugin initialization.
Create KMS client and scan datadir to find out which keys and versions
are present.
*/
static int plugin_init(void *p)
{
DBUG_ENTER("plugin_init");
client = new KMSClient();
if (!client)
{
sql_print_error("Can not initialize KMS client");
DBUG_RETURN(-1);
}
InitializeAWSLogging(Aws::MakeShared<MySQLLogSystem>("aws_key_management_plugin", (Aws::Utils::Logging::LogLevel) log_level));
#ifdef HAVE_PSI_INTERFACE
mysql_mutex_register("aws_key_management", &mtx_info, 1);
#endif
mysql_mutex_init(mtx_key, &mtx, NULL);
MY_DIR *dirp = my_dir(".", MYF(0));
if (!dirp)
{
sql_print_error("Can't scan current directory");
DBUG_RETURN(-1);
}
for (unsigned int i=0; i < dirp->number_of_files; i++)
{
KEY_INFO info;
if (extract_id_and_version(dirp->dir_entry[i].name, &info.key_id, &info.key_version) == 0)
{
key_info_cache[KEY_ID_AND_VERSION(info.key_id, info.key_version)]= info;
latest_version_cache[info.key_id]= max(info.key_version, latest_version_cache[info.key_id]);
}
}
my_dirend(dirp);
DBUG_RETURN(0);
}
static int plugin_deinit(void *p)
{
DBUG_ENTER("plugin_deinit");
latest_version_cache.clear();
key_info_cache.clear();
mysql_mutex_destroy(&mtx);
delete client;
ShutdownAWSLogging();
DBUG_RETURN(0);
}
/* Generate filename to store the ciphered key */
static void format_keyfile_name(char *buf, size_t size, uint key_id, uint version)
{
snprintf(buf, size, "aws-kms-key.%u.%u", key_id, version);
}
/* Extract key id and version from file name */
static int extract_id_and_version(const char *name, uint *id, uint *ver)
{
int len;
int n= sscanf(name, "aws-kms-key.%u.%u%n", id, ver, &len);
if (n == 2 && *id > 0 && *ver > 0 && len == (int)strlen(name))
return 0;
return 1;
}
/*
Decrypt key stored in aws-kms-key.<id>.<version>
Cache the decrypted key.
*/
static int load_key(KEY_INFO *info)
{
int ret;
char path[256];
DBUG_ENTER("load_key");
DBUG_PRINT("enter", ("id=%u,ver=%u", info->key_id, info->key_version));
format_keyfile_name(path, sizeof(path), info->key_id, info->key_version);
ret= aws_decrypt_key(path, info);
if (ret)
info->load_failed= true;
latest_version_cache[info->key_id]= max(latest_version_cache[info->key_id], info->key_version);
key_info_cache[KEY_ID_AND_VERSION(info->key_id, info->key_version)]= *info;
if (!ret)
{
sql_print_information("AWS KMS plugin: loaded key %u, version %u, key length %u bit",
info->key_id, info->key_version,(uint)info->length*8);
}
else
{
sql_print_warning("AWS KMS plugin: key %u, version %u could not be decrypted",
info->key_id, info->key_version);
}
DBUG_RETURN(ret);
}
/*
Get latest version for the key.
If key is not decrypted yet, this function also decrypt the key
and error will be returned if decryption fails.
The reason for that is that Innodb crashes
in case errors are returned by get_key(),
A new key will be created if it does not exist, provided there is
valid master_key_id.
*/
static unsigned int get_latest_key_version(unsigned int key_id)
{
unsigned int ret;
DBUG_ENTER("get_latest_key_version");
mysql_mutex_lock(&mtx);
ret= get_latest_key_version_nolock(key_id);
mysql_mutex_unlock(&mtx);
DBUG_PRINT("info", ("key=%u,ret=%u", key_id, ret));
DBUG_RETURN(ret);
}
static unsigned int get_latest_key_version_nolock(unsigned int key_id)
{
KEY_INFO info;
uint ver;
DBUG_ENTER("get_latest_key_version_nolock");
ver= latest_version_cache[key_id];
if (ver > 0)
{
info= key_info_cache[KEY_ID_AND_VERSION(key_id, ver)];
}
if (info.load_failed)
{
/* Decryption failed previously, don't retry */
DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID);
}
else if (ver > 0)
{
/* Key exists already, return it*/
if (info.length > 0)
DBUG_RETURN(ver);
}
else // (ver == 0)
{
/* Generate a new key, version 1 */
if (!master_key_id[0])
{
my_printf_error(ER_UNKNOWN_ERROR,
"Can't generate encryption key %u, because 'aws_key_management_master_key_id' parameter is not set",
MYF(0), key_id);
DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID);
}
if (aws_generate_datakey(key_id, 1) != 0)
DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID);
info.key_id= key_id;
info.key_version= 1;
info.length= 0;
}
if (load_key(&info))
DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID);
DBUG_RETURN(info.key_version);
}
/*
Decrypt a file with KMS
*/
static int aws_decrypt_key(const char *path, KEY_INFO *info)
{
DBUG_ENTER("aws_decrypt_key");
/* Read file content into memory */
ifstream ifs(path, ios::binary | ios::ate);
if (!ifs.good())
{
sql_print_error("can't open file %s", path);
DBUG_RETURN(-1);
}
size_t pos = (size_t)ifs.tellg();
if (!pos || pos == SIZE_T_MAX)
{
sql_print_error("invalid key file %s", path);
DBUG_RETURN(-1);
}
std::vector<char> contents(pos);
ifs.seekg(0, ios::beg);
ifs.read(&contents[0], pos);
/* Decrypt data the with AWS */
DecryptRequest request;
Aws::Utils::ByteBuffer byteBuffer((unsigned char *)contents.data(), pos);
request.SetCiphertextBlob(byteBuffer);
DecryptOutcome outcome = client->Decrypt(request);
if (!outcome.IsSuccess())
{
sql_print_error("AWS KMS plugin: Decrypt failed for %s : %s", path,
outcome.GetError().GetMessage().c_str());
DBUG_RETURN(-1);
}
Aws::Utils::ByteBuffer plaintext = outcome.GetResult().GetPlaintext();
size_t len = plaintext.GetLength();
if (len > (int)sizeof(info->data))
{
sql_print_error("AWS KMS plugin: encoding key too large for %s", path);
DBUG_RETURN(ENCRYPTION_KEY_BUFFER_TOO_SMALL);
}
memcpy(info->data, plaintext.GetUnderlyingData(), len);
info->length= len;
DBUG_RETURN(0);
}
/* Generate a new datakey and store it a file */
static int aws_generate_datakey(uint keyid, uint version)
{
DBUG_ENTER("aws_generate_datakey");
GenerateDataKeyWithoutPlaintextRequest request;
request.SetKeyId(master_key_id);
request.SetKeySpec(DataKeySpecMapper::GetDataKeySpecForName(key_spec_names[key_spec]));
GenerateDataKeyWithoutPlaintextOutcome outcome;
outcome= client->GenerateDataKeyWithoutPlaintext(request);
if (!outcome.IsSuccess())
{
sql_print_error("AWS KMS plugin : GenerateDataKeyWithoutPlaintext failed : %s - %s",
outcome.GetError().GetExceptionName().c_str(),
outcome.GetError().GetMessage().c_str());
DBUG_RETURN(-1);
}
string out;
char filename[20];
Aws::Utils::ByteBuffer byteBuffer = outcome.GetResult().GetCiphertextBlob();
format_keyfile_name(filename, sizeof(filename), keyid, version);
int fd= my_open(filename, O_RDWR | O_CREAT, 0);
if (fd < 0)
{
sql_print_error("AWS KMS plugin: Can't create file %s", filename);
DBUG_RETURN(-1);
}
size_t len= byteBuffer.GetLength();
if (my_write(fd, byteBuffer.GetUnderlyingData(), len, 0) != len)
{
sql_print_error("AWS KMS plugin: can't write to %s", filename);
my_close(fd, 0);
my_delete(filename, 0);
DBUG_RETURN(-1);
}
my_close(fd, 0);
sql_print_information("AWS KMS plugin: generated encrypted datakey for key id=%u, version=%u",
keyid, version);
DBUG_RETURN(0);
}
/* Key rotation for a single key */
static int rotate_single_key(uint key_id)
{
uint ver;
ver= latest_version_cache[key_id];
if (!ver)
{
my_printf_error(ER_UNKNOWN_ERROR, "key %u does not exist", MYF(ME_JUST_WARNING), key_id);
return -1;
}
else if (aws_generate_datakey(key_id, ver + 1))
{
my_printf_error(ER_UNKNOWN_ERROR, "Could not generate datakey for key id= %u, ver= %u",
MYF(ME_JUST_WARNING), key_id, ver);
return -1;
}
else
{
KEY_INFO info;
info.key_id= key_id;
info.key_version = ver + 1;
if (load_key(&info))
{
my_printf_error(ER_UNKNOWN_ERROR, "Could not load datakey for key id= %u, ver= %u",
MYF(ME_JUST_WARNING), key_id, ver);
return -1;
}
}
return 0;
}
/* Key rotation for all key ids */
static int rotate_all_keys()
{
int ret= 0;
for (map<uint, uint>::iterator it= latest_version_cache.begin(); it != latest_version_cache.end(); it++)
{
ret= rotate_single_key(it->first);
if (ret)
break;
}
return ret;
}
static void update_rotate(MYSQL_THD, struct st_mysql_sys_var *, void *, const void *val)
{
if (!master_key_id[0])
{
my_printf_error(ER_UNKNOWN_ERROR,
"aws_key_management_master_key_id must be set to generate new data keys", MYF(ME_JUST_WARNING));
return;
}
mysql_mutex_lock(&mtx);
rotate_key= *(int *)val;
switch (rotate_key)
{
case 0:
break;
case -1:
rotate_all_keys();
break;
default:
rotate_single_key(rotate_key);
break;
}
rotate_key= 0;
mysql_mutex_unlock(&mtx);
}
static unsigned int get_key(
unsigned int key_id,
unsigned int version,
unsigned char* dstbuf,
unsigned int* buflen)
{
KEY_INFO info;
DBUG_ENTER("get_key");
mysql_mutex_lock(&mtx);
info= key_info_cache[KEY_ID_AND_VERSION(key_id, version)];
if (info.length == 0 && !info.load_failed)
{
info.key_id= key_id;
info.key_version= version;
load_key(&info);
}
mysql_mutex_unlock(&mtx);
if (info.load_failed)
DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID);
if (*buflen < info.length)
{
*buflen= info.length;
DBUG_RETURN(ENCRYPTION_KEY_BUFFER_TOO_SMALL);
}
*buflen= info.length;
memcpy(dstbuf, info.data, info.length);
DBUG_RETURN(0);
}
/* Plugin defs */
struct st_mariadb_encryption aws_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_key_version,
get_key,
// use default encrypt/decrypt functions
0, 0, 0, 0, 0
};
static TYPELIB key_spec_typelib =
{
array_elements(key_spec_names) - 1, "",
key_spec_names, NULL
};
const char *log_level_names[] =
{
"Off",
"Fatal",
"Error",
"Warn",
"Info",
"Debug",
"Trace",
0
};
static TYPELIB log_level_typelib =
{
array_elements(log_level_names) - 1, "",
log_level_names, NULL
};
static MYSQL_SYSVAR_STR(master_key_id, master_key_id,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
"Key id for master encryption key. Used to create new datakeys. If not set, no new keys will be created",
NULL, NULL, "");
static MYSQL_SYSVAR_ENUM(key_spec, key_spec,
PLUGIN_VAR_RQCMDARG,
"Encryption algorithm used to create new keys.",
NULL, NULL, 0, &key_spec_typelib);
static MYSQL_SYSVAR_ENUM(log_level, log_level,
PLUGIN_VAR_RQCMDARG,
"Logging for AWS API",
NULL, NULL, 0, &log_level_typelib);
static MYSQL_SYSVAR_INT(rotate_key, rotate_key,
PLUGIN_VAR_RQCMDARG,
"Set this variable to key id to perform rotation of the key. Specify -1 to rotate all keys",
NULL, update_rotate, 0, -1, INT_MAX, 1);
static struct st_mysql_sys_var* settings[]= {
MYSQL_SYSVAR(master_key_id),
MYSQL_SYSVAR(key_spec),
MYSQL_SYSVAR(rotate_key),
MYSQL_SYSVAR(log_level),
NULL
};
/*
Plugin library descriptor
*/
maria_declare_plugin(aws_key_management)
{
MariaDB_ENCRYPTION_PLUGIN,
&aws_key_management_plugin,
"aws_key_management",
"MariaDB Corporation",
"AWS key management plugin",
PLUGIN_LICENSE_GPL,
plugin_init,
plugin_deinit,
0x0100,
NULL,
settings,
"1.0",
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
}
maria_declare_plugin_end;
......@@ -9,7 +9,7 @@ IF(ESSENTIALS)
ENDIF()
ELSE()
SET(CPACK_COMPONENTS_USED
"Server;Client;Development;SharedLibraries;Embedded;Documentation;IniFiles;Readme;Debuginfo;Common;connect-engine;ClientPlugins;gssapi-server;gssapi-client")
"Server;Client;Development;SharedLibraries;Embedded;Documentation;IniFiles;Readme;Debuginfo;Common;connect-engine;ClientPlugins;gssapi-server;gssapi-client;aws-key-management")
ENDIF()
SET( WIX_FEATURE_MySQLServer_EXTRA_FEATURES "DBInstance;SharedClientServerComponents")
......@@ -57,7 +57,7 @@ SET(CPACK_COMPONENT_GROUP_MYSQLSERVER_DESCRIPTION "Install server")
#Miscellaneous (hidden) components, part of server / or client programs
FOREACH(comp connect-engine ClientPlugins gssapi-server gssapi-client)
FOREACH(comp connect-engine ClientPlugins gssapi-server gssapi-client aws-key-management)
STRING(TOUPPER "${comp}" comp)
SET(CPACK_COMPONENT_${comp}_GROUP "MySQLServer")
SET(CPACK_COMPONENT_${comp}_HIDDEN 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment