138 lines
6.6 KiB
SQL
138 lines
6.6 KiB
SQL
-- 消息加密密钥管理。
|
|
-- 可重复执行。根 KEK 只在首次执行时生成,重复执行不会覆盖已有值。
|
|
|
|
SET NAMES utf8mb4;
|
|
SET @now := NOW();
|
|
|
|
SET @im_sql = IF(
|
|
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'im_tenant_config'
|
|
AND COLUMN_NAME = 'message_encryption_enabled') = 0,
|
|
'ALTER TABLE `im_tenant_config` ADD COLUMN `message_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否启用消息加密'' AFTER `local_moderation_enabled`',
|
|
'SELECT 1'
|
|
);
|
|
PREPARE im_stmt FROM @im_sql;
|
|
EXECUTE im_stmt;
|
|
DEALLOCATE PREPARE im_stmt;
|
|
|
|
CREATE TABLE IF NOT EXISTS `im_message_encryption_keys` (
|
|
`id` bigint NOT NULL AUTO_INCREMENT,
|
|
`tenant_id` bigint NOT NULL COMMENT '商户ID',
|
|
`key_version` int unsigned NOT NULL COMMENT '密钥版本',
|
|
`algorithm` varchar(32) NOT NULL DEFAULT 'AES-256-GCM' COMMENT '数据加密算法',
|
|
`encrypted_dek` blob NOT NULL COMMENT '由根KEK包裹后的商户DEK',
|
|
`dek_nonce` varbinary(12) NOT NULL COMMENT '包裹DEK使用的随机nonce',
|
|
`status` varchar(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/active/retired/disabled',
|
|
`activated_at` datetime DEFAULT NULL,
|
|
`retired_at` datetime DEFAULT NULL,
|
|
`remark` varchar(255) NOT NULL DEFAULT '',
|
|
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`created_by` bigint NOT NULL DEFAULT 0,
|
|
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
`updated_by` bigint NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uk_im_message_key_tenant_version` (`tenant_id`, `key_version`),
|
|
KEY `idx_im_message_key_tenant_status` (`tenant_id`, `status`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商户消息加密密钥版本';
|
|
|
|
INSERT INTO `hg_sys_dict_type`
|
|
(`pid`, `name`, `type`, `sort`, `remark`, `status`, `created_at`, `updated_at`)
|
|
SELECT 0, 'IM内部安全材料', 'im_internal_secret', 9999,
|
|
'仅供服务端读取,通用字典接口禁止查询和维护', 1, @now, @now
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM `hg_sys_dict_type` WHERE `type` = 'im_internal_secret'
|
|
);
|
|
|
|
INSERT INTO `hg_sys_dict_data`
|
|
(`label`, `value`, `value_type`, `type`, `list_class`, `is_default`, `sort`, `remark`, `status`, `created_at`, `updated_at`)
|
|
SELECT 'core_material_01', TO_BASE64(RANDOM_BYTES(32)), 'string', 'im_internal_secret',
|
|
'', 2, 1, '消息DEK包裹根密钥KEK,请勿通过后台展示或修改', 1, @now, @now
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM `hg_sys_dict_data`
|
|
WHERE `type` = 'im_internal_secret' AND `label` = 'core_material_01'
|
|
);
|
|
|
|
SET @imRootId := (SELECT `id` FROM `hg_admin_menu` WHERE `name` = 'imManager' LIMIT 1);
|
|
SET @settingsId := (SELECT `id` FROM `hg_admin_menu` WHERE `name` = 'imSystemSettings' LIMIT 1);
|
|
|
|
INSERT INTO `hg_admin_menu`
|
|
(`pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`,
|
|
`permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`,
|
|
`frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`,
|
|
`status`, `created_at`, `updated_at`)
|
|
SELECT @settingsId, '消息密钥管理', 'imMessageEncryptionIndex', 'message-encryption/index',
|
|
'KeyOutlined', 2, '', '/imMessageEncryption/list', '', '/imMessageEncryption/index',
|
|
1, 'imManager', 0, 0, '', 0, 0, 0, 3,
|
|
CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' '), 80,
|
|
'商户消息加密开关及密钥版本管理', 1, @now, @now
|
|
WHERE @settingsId IS NOT NULL
|
|
AND NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name` = 'imMessageEncryptionIndex');
|
|
|
|
SET @keyMenuId := (SELECT `id` FROM `hg_admin_menu` WHERE `name` = 'imMessageEncryptionIndex' LIMIT 1);
|
|
|
|
UPDATE `hg_admin_menu`
|
|
SET `pid` = @settingsId,
|
|
`title` = '消息密钥管理',
|
|
`path` = 'message-encryption/index',
|
|
`icon` = 'KeyOutlined',
|
|
`permissions` = '/imMessageEncryption/list',
|
|
`component` = '/imMessageEncryption/index',
|
|
`active_menu` = 'imManager',
|
|
`level` = 3,
|
|
`tree` = CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' '),
|
|
`sort` = 80,
|
|
`hidden` = 0,
|
|
`status` = 1,
|
|
`updated_at` = @now
|
|
WHERE `id` = @keyMenuId;
|
|
|
|
INSERT INTO `hg_admin_menu`
|
|
(`pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`,
|
|
`permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`,
|
|
`frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`,
|
|
`status`, `created_at`, `updated_at`)
|
|
SELECT @keyMenuId, '初始化密钥', 'imMessageEncryptionInitialize', '', '', 3, '',
|
|
'/imMessageEncryption/initialize', '', '', 1, '', 0, 0, '', 0, 1, 0, 4,
|
|
CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' tr_', @keyMenuId, ' '), 10, '', 1, @now, @now
|
|
WHERE @keyMenuId IS NOT NULL
|
|
AND NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name` = 'imMessageEncryptionInitialize');
|
|
|
|
INSERT INTO `hg_admin_menu`
|
|
(`pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`,
|
|
`permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`,
|
|
`frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`,
|
|
`status`, `created_at`, `updated_at`)
|
|
SELECT @keyMenuId, '轮换密钥', 'imMessageEncryptionRotate', '', '', 3, '',
|
|
'/imMessageEncryption/rotate', '', '', 1, '', 0, 0, '', 0, 1, 0, 4,
|
|
CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' tr_', @keyMenuId, ' '), 20, '', 1, @now, @now
|
|
WHERE @keyMenuId IS NOT NULL
|
|
AND NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name` = 'imMessageEncryptionRotate');
|
|
|
|
INSERT INTO `hg_admin_menu`
|
|
(`pid`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`,
|
|
`permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`,
|
|
`frame_src`, `keep_alive`, `hidden`, `affix`, `level`, `tree`, `sort`, `remark`,
|
|
`status`, `created_at`, `updated_at`)
|
|
SELECT @keyMenuId, '切换消息加密', 'imMessageEncryptionSwitch', '', '', 3, '',
|
|
'/imMessageEncryption/switch', '', '', 1, '', 0, 0, '', 0, 1, 0, 4,
|
|
CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' tr_', @keyMenuId, ' '), 30, '', 1, @now, @now
|
|
WHERE @keyMenuId IS NOT NULL
|
|
AND NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name` = 'imMessageEncryptionSwitch');
|
|
|
|
UPDATE `hg_admin_menu`
|
|
SET `level` = 4,
|
|
`tree` = CONCAT('tr_', @imRootId, ' tr_', @settingsId, ' tr_', @keyMenuId, ' '),
|
|
`updated_at` = @now
|
|
WHERE `pid` = @keyMenuId AND `type` = 3;
|
|
|
|
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`, `menu_id`)
|
|
SELECT 1, `id` FROM `hg_admin_menu`
|
|
WHERE `name` IN (
|
|
'imManager',
|
|
'imSystemSettings',
|
|
'imMessageEncryptionIndex',
|
|
'imMessageEncryptionInitialize',
|
|
'imMessageEncryptionRotate',
|
|
'imMessageEncryptionSwitch'
|
|
);
|