You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何开发从API导入主密钥的MariaDB自定义加密插件

开发MariaDB API驱动的自定义加密密钥管理插件

MariaDB的密钥管理插件需要实现官方定义的key_management_service接口,核心是替换本地密钥读取逻辑为API拉取。以下是简化版的实现思路、示例源码及常见问题解决方法:

简化版示例源码

#include <mysql/plugin_key_management.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <mysql/my_getopt.h>

// 存储从API获取的主密钥
static unsigned char *global_master_key = NULL;
static size_t global_key_len = 0;
// 自定义配置项:API地址
static const char *api_url = NULL;

// CURL回调:接收API返回的密钥数据
static size_t write_key_data(void *ptr, size_t size, size_t nmemb, void *stream) {
    size_t realsize = size * nmemb;
    unsigned char **key_ptr = (unsigned char **)stream;
    
    *key_ptr = realloc(*key_ptr, global_key_len + realsize + 1);
    if (*key_ptr == NULL) return 0;
    
    memcpy(&(*key_ptr)[global_key_len], ptr, realsize);
    global_key_len += realsize;
    (*key_ptr)[global_key_len] = '\0';
    
    return realsize;
}

// 从API拉取主密钥(支持携带认证头,示例省略)
static int fetch_master_key() {
    CURL *curl = curl_easy_init();
    if (!curl) return 1;
    
    curl_easy_setopt(curl, CURLOPT_URL, api_url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_key_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &global_master_key);
    
    CURLcode res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    
    return (res != CURLE_OK) ? 1 : 0;
}

// 插件配置项定义
static struct my_option options[] = {
    {"key_management_api_url", 'u', "API URL to fetch master key", (char**)&api_url, (char**)&api_url, NULL,
     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
    {NULL, 0, NULL, NULL, NULL, NULL, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};

// 插件初始化:读取配置+拉取密钥
static int key_management_init(void *p) {
    if (my_getopt_handle_options(&mysql_extra_options, options, NULL, 0, 0, 0)) {
        return 1;
    }
    return fetch_master_key();
}

// 核心函数:提供密钥给MariaDB加密模块
static int key_management_get_key(const char *key_id, unsigned char **key, size_t *key_len) {
    // 实际场景建议用主密钥派生子密钥(如HKDF),这里直接返回API拉取的密钥
    *key = malloc(global_key_len);
    if (*key == NULL) return 1;
    
    memcpy(*key, global_master_key, global_key_len);
    *key_len = global_key_len;
    return 0;
}

// 插件清理:释放密钥内存
static void key_management_deinit(void *p) {
    if (global_master_key != NULL) {
        free(global_master_key);
        global_master_key = NULL;
        global_key_len = 0;
    }
}

// 插件接口结构体
static struct st_mysql_key_management key_management_plugin = {
    MYSQL_KEY_MANAGEMENT_INTERFACE_VERSION,
    key_management_init,
    key_management_deinit,
    key_management_get_key,
    NULL, // 可选:密钥旋转函数
    NULL  // 可选:密钥存储函数
};

// 插件入口声明
mysql_declare_plugin(key_management_api) {
    MYSQL_KEY_MANAGEMENT_PLUGIN,
    &key_management_plugin,
    "key_management_api",
    "Ankit",
    "Key management plugin fetching keys via API",
    PLUGIN_LICENSE_GPL,
    key_management_init,
    key_management_deinit,
    0x0100,
    NULL,
    options,
    NULL,
    0,
} mysql_declare_plugin_end;

编译与配置

  1. 编译命令:需链接MariaDB开发库和libcurl
    gcc -fPIC -shared -o key_management_api.so key_management_api.c $(mysql_config --cflags --libs) -lcurl
    
  2. 部署插件:将生成的.so文件放到MariaDB插件目录(可通过SHOW VARIABLES LIKE 'plugin_dir';查看)
  3. 配置my.cnf:
    [mysqld]
    plugin_load_add = key_management_api.so
    key_management_api_url = "https://your-key-service.example.com/master-key"
    encrypt_tables = ON
    

常见问题解决

  • 未定义关键字/符号错误:
    • 确保编译时使用mysql_config --cflags --libs获取正确的编译参数,链接MariaDB开发库
    • 检查MYSQL_KEY_MANAGEMENT_INTERFACE_VERSION是否与当前MariaDB版本一致(可在mysql/plugin_key_management.h中查看定义)
  • 版本不匹配:
    • 插件必须与MariaDB主版本匹配(如10.5版本插件无法在10.11运行),建议基于对应版本的MariaDB源码插件模板开发
    • 若自行编译MariaDB,可将插件代码放入plugin/key_management/目录,修改CMakeLists.txt一起编译,避免兼容问题

内容的提问来源于stack exchange,提问作者Ankit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:17:19