feat: 增加商户消息加密密钥管理
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
-- 消息加密密钥管理。
|
||||
-- 可重复执行。根 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'
|
||||
);
|
||||
Reference in New Issue
Block a user