From abce8784db09d0bf510dd1dda055511e2a47c1f6 Mon Sep 17 00:00:00 2001 From: waner Date: Wed, 20 May 2026 17:58:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=AF=86=E9=92=A5=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/RoleUkeyBindingRepository.java | 2 + .../impl/RoleUkeyBindingRepositoryImpl.java | 9 +++++ .../service/impl/AuthAdminServiceImpl.java | 16 ++++++-- .../mk/service/impl/LmkServiceImpl.java | 20 +++------- src/main/resources/application.yml | 2 +- .../auth/service/AuthAdminServiceTest.java | 37 +++++++++++++++++++ .../modules/auth/service/AuthServiceTest.java | 9 +++++ .../modules/mk/service/LmkServiceTest.java | 22 +++++++++-- 8 files changed, 95 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java b/src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java index c34bba1..88bcba3 100644 --- a/src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java +++ b/src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java @@ -8,6 +8,8 @@ public interface RoleUkeyBindingRepository { Optional findById(Long id); + Optional findByRoleCodeAndUidAndUkeySerial(String roleCode, Integer uid, String ukeySerial); + List findActiveByRoleCodeAndUid(String roleCode, Integer uid); List findActiveByRoleCode(String roleCode); diff --git a/src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java b/src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java index 7b66b99..0ed11e9 100644 --- a/src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java +++ b/src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java @@ -1,5 +1,6 @@ package com.cisd.tms.modules.auth.repository.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.cisd.tms.modules.auth.entity.RoleUkeyBindingEntity; import com.cisd.tms.modules.auth.mapper.RoleUkeyBindingMapper; import com.cisd.tms.modules.auth.repository.RoleUkeyBindingRepository; @@ -21,6 +22,14 @@ public class RoleUkeyBindingRepositoryImpl implements RoleUkeyBindingRepository return Optional.ofNullable(roleUkeyBindingMapper.selectById(id)); } + @Override + public Optional findByRoleCodeAndUidAndUkeySerial(String roleCode, Integer uid, String ukeySerial) { + return Optional.ofNullable(roleUkeyBindingMapper.selectOne(new LambdaQueryWrapper() + .eq(RoleUkeyBindingEntity::getRoleCode, roleCode) + .eq(RoleUkeyBindingEntity::getUid, uid) + .eq(RoleUkeyBindingEntity::getUkeySerial, ukeySerial))); + } + @Override public List findActiveByRoleCodeAndUid(String roleCode, Integer uid) { return roleUkeyBindingMapper.selectActiveByRoleCodeAndUid(roleCode, uid); diff --git a/src/main/java/com/cisd/tms/modules/auth/service/impl/AuthAdminServiceImpl.java b/src/main/java/com/cisd/tms/modules/auth/service/impl/AuthAdminServiceImpl.java index dbcc925..dce0697 100644 --- a/src/main/java/com/cisd/tms/modules/auth/service/impl/AuthAdminServiceImpl.java +++ b/src/main/java/com/cisd/tms/modules/auth/service/impl/AuthAdminServiceImpl.java @@ -312,10 +312,10 @@ public class AuthAdminServiceImpl implements AuthAdminService { authFullAccountRepository.findByRoleCodeAndUid(targetRoleCode, uid) .orElseThrow(() -> new BizException(ErrorCode.VALIDATE_FAILED.getCode(), "目标角色完整账号不存在")); + RoleUkeyBindingEntity binding = findReusableBinding(targetRoleCode, uid, ukeySerial, ukeyPubkey); if (RoleCode.SUPER_ADMIN != targetRole) { unbindActiveSeatBindings(targetRoleCode, uid); } - RoleUkeyBindingEntity binding = findExistingActiveBinding(targetRoleCode, uid, ukeySerial, ukeyPubkey); if (binding.getId() == null) { binding.setId((long) Math.abs(Objects.hash(targetRoleCode, uid, ukeySerial, TraceIdUtil.newTraceId()))); binding.setRoleCode(targetRoleCode); @@ -340,15 +340,23 @@ public class AuthAdminServiceImpl implements AuthAdminService { roleUkeyBindingRepository.update(binding); } - private RoleUkeyBindingEntity findExistingActiveBinding( + private RoleUkeyBindingEntity findReusableBinding( String roleCode, Integer uid, String ukeySerial, String ukeyPubkey + ) { + return roleUkeyBindingRepository.findByRoleCodeAndUidAndUkeySerial(roleCode, uid, ukeySerial) + .orElseGet(() -> findExistingActiveBinding(roleCode, uid, ukeyPubkey)); + } + + private RoleUkeyBindingEntity findExistingActiveBinding( + String roleCode, + Integer uid, + String ukeyPubkey ) { return roleUkeyBindingRepository.findActiveByRoleCodeAndUid(roleCode, uid).stream() - .filter(binding -> Objects.equals(binding.getUkeySerial(), ukeySerial) - || Objects.equals(binding.getUkeyPubkey(), ukeyPubkey)) + .filter(binding -> Objects.equals(binding.getUkeyPubkey(), ukeyPubkey)) .findFirst() .orElseGet(RoleUkeyBindingEntity::new); } diff --git a/src/main/java/com/cisd/tms/modules/mk/service/impl/LmkServiceImpl.java b/src/main/java/com/cisd/tms/modules/mk/service/impl/LmkServiceImpl.java index 808fa8c..89ea688 100644 --- a/src/main/java/com/cisd/tms/modules/mk/service/impl/LmkServiceImpl.java +++ b/src/main/java/com/cisd/tms/modules/mk/service/impl/LmkServiceImpl.java @@ -267,19 +267,11 @@ public class LmkServiceImpl implements LmkService { if (deviceStatus != null) { log.info("device status:{}/lmk seed mac:{}", deviceStatus.getFsmState(), recoveryResult.getLmkSeedMac()); } - clearKeyEntityRegistry(); + runMasterKeySecurityMaintenance(masterKeyActivateEntity, "主密钥恢复后"); MasterKeyStateResult result = new MasterKeyStateResult(); result.setStatus(true); result.setSeedMac(Hex.toHexString(recoveryResult.getLmkSeedMac())); - try { - masterKeyActivateEntity.setActivationStatus(false); - masterKeyActivateEntity.setEverInitialized(false); - masterKeyActivateRepository.update(masterKeyActivateEntity); - } catch (RuntimeException ex) { - log.error("主密钥恢复后更新激活记录失败", ex); - } - return result; } @@ -642,29 +634,29 @@ public class LmkServiceImpl implements LmkService { private void schedulePostMasterKeyInitMaintenance(MasterKeyActivateEntity masterKeyActivateEntity) { try { - masterKeyPostInitExecutor.execute(() -> runPostMasterKeyInitMaintenance(masterKeyActivateEntity)); + masterKeyPostInitExecutor.execute(() -> runMasterKeySecurityMaintenance(masterKeyActivateEntity, "主密钥初始化后")); } catch (RuntimeException ex) { log.error("提交主密钥初始化后置维护任务失败", ex); } } - private void runPostMasterKeyInitMaintenance(MasterKeyActivateEntity masterKeyActivateEntity) { + private void runMasterKeySecurityMaintenance(MasterKeyActivateEntity masterKeyActivateEntity, String operationName) { try { clearKeyEntityRegistry(); } catch (RuntimeException ex) { - log.error("主密钥初始化后清理实体密钥登记表失败", ex); + log.error("{}清理实体密钥登记表失败", operationName, ex); } try { authSecurityResetService.resetAfterMasterKeyInitialized(); } catch (RuntimeException ex) { - log.error("主密钥初始化后重置认证状态失败", ex); + log.error("{}重置认证状态失败", operationName, ex); } try { masterKeyActivateEntity.setActivationStatus(false); masterKeyActivateEntity.setEverInitialized(false); masterKeyActivateRepository.update(masterKeyActivateEntity); } catch (RuntimeException ex) { - log.error("主密钥初始化后更新激活记录失败", ex); + log.error("{}更新激活记录失败", operationName, ex); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1f771a5..de6cbe4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -188,7 +188,7 @@ tms: disk-usage-path: ${TMS_DEVICE_RUNTIME_STATUS_DISK_USAGE_PATH:/home/tms} upgrade: # 升级包解压和脚本执行暂存目录。 - staging-root-dir: ${TMS_UPGRADE_STAGING_ROOT_DIR:/home/tmp/tms-upgrade-staging} + staging-root-dir: ${TMS_UPGRADE_STAGING_ROOT_DIR:/home/tms/tmp/tms-upgrade-staging} # 升级任务统一日志目录。 log-dir: ${TMS_UPGRADE_LOG_DIR:/home/tms/tmp/tms-upgrade-logs} # 升级包验签使用的公钥 PEM 文件路径;为空时升级预检会拒绝通过。 diff --git a/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java b/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java index 0e47a35..1005188 100644 --- a/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java +++ b/src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java @@ -190,6 +190,34 @@ class AuthAdminServiceTest { && item.getUnboundAt() != null)); } + @Test + void shouldRebindSingleSeatAdminSameSerialByReusingExistingBindingRow() { + InMemoryRoleAccountRepository roles = new InMemoryRoleAccountRepository(); + InMemoryAuthFullAccountRepository accounts = new InMemoryAuthFullAccountRepository(); + InMemoryRoleUkeyBindingRepository bindings = new InMemoryRoleUkeyBindingRepository(); + roles.save(role(RoleCode.KEY_ADMIN, RoleAccountStatus.ACTIVE)); + accounts.save(account(RoleCode.KEY_ADMIN, 1, "key-admin-01", "HASH-OLD", "SALT-OLD")); + RoleUkeyBindingEntity existing = binding(RoleCode.KEY_ADMIN, 1, "UK-SAME", "PUB-OLD", "SIG-OLD"); + bindings.save(existing); + LmkService lmkService = Mockito.mock(LmkService.class); + Mockito.when(lmkService.exportIkPublicKeyHex()).thenReturn("IK-PUB-001"); + Mockito.when(lmkService.signIk(Mockito.anyString())).thenReturn("ISSUE-SIGN-SAME"); + UKeySignDTO dto = new UKeySignDTO(); + dto.setPubKey("PUB-NEW"); + dto.setUkeySerial("UK-SAME"); + dto.setUid(1); + + service(roles, accounts, bindings, lmkService) + .issueUkeyBindingSign(RoleCode.SUPER_ADMIN.getCode(), AuthLevel.FULL.name(), RoleCode.KEY_ADMIN.getCode(), dto); + + Assertions.assertEquals(1, bindings.all().size()); + RoleUkeyBindingEntity rebound = bindings.findActiveByRoleCodeAndUid(RoleCode.KEY_ADMIN.getCode(), 1).get(0); + Assertions.assertEquals(existing.getId(), rebound.getId()); + Assertions.assertEquals("UK-SAME", rebound.getUkeySerial()); + Assertions.assertEquals("PUB-NEW", rebound.getUkeyPubkey()); + Assertions.assertEquals("ISSUE-SIGN-SAME", rebound.getIssuerSign()); + } + @Test void shouldBootstrapSuperAdminUkeyWithoutLoginContext() { InMemoryRoleAccountRepository roles = new InMemoryRoleAccountRepository(); @@ -506,6 +534,15 @@ class AuthAdminServiceTest { .findFirst(); } + @Override + public Optional findByRoleCodeAndUidAndUkeySerial(String roleCode, Integer uid, String ukeySerial) { + return store.stream() + .filter(entity -> roleCode.equals(entity.getRoleCode())) + .filter(entity -> uid.equals(entity.getUid())) + .filter(entity -> ukeySerial.equals(entity.getUkeySerial())) + .findFirst(); + } + @Override public List findActiveByRoleCode(String roleCode) { return store.stream() diff --git a/src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java b/src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java index 7f31623..b9a5a72 100644 --- a/src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java +++ b/src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java @@ -510,6 +510,15 @@ class AuthServiceTest { .findFirst(); } + @Override + public Optional findByRoleCodeAndUidAndUkeySerial(String roleCode, Integer uid, String ukeySerial) { + return store.stream() + .filter(entity -> roleCode.equals(entity.getRoleCode())) + .filter(entity -> uid.equals(entity.getUid())) + .filter(entity -> ukeySerial.equals(entity.getUkeySerial())) + .findFirst(); + } + @Override public List findActiveByRoleCode(String roleCode) { return store.stream() diff --git a/src/test/java/com/cisd/tms/modules/mk/service/LmkServiceTest.java b/src/test/java/com/cisd/tms/modules/mk/service/LmkServiceTest.java index 9b26425..bf615bd 100644 --- a/src/test/java/com/cisd/tms/modules/mk/service/LmkServiceTest.java +++ b/src/test/java/com/cisd/tms/modules/mk/service/LmkServiceTest.java @@ -379,6 +379,7 @@ class LmkServiceTest { PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class); MasterKeyActivateRepository masterKeyActivateRepository = Mockito.mock(MasterKeyActivateRepository.class); MasterKeyInitProperties properties = configuredPins("MTIzNDU2Nzg=", "ODc2NTQzMjE="); + allowMasterKeyInit(masterKeyActivateRepository); MasterKeyRecoveryResult recoveryResult = new MasterKeyRecoveryResult(); recoveryResult.setLmkSeedMac(hex("1112131415161718")); recoveryResult.setDeviceStatus(new DeviceStatusResult()); @@ -414,21 +415,36 @@ class LmkServiceTest { } @Test - void shouldClearKeyEntityRegistryAfterMasterKeyRecoverySucceeds() { + void shouldRunSecurityCleanupAfterMasterKeyRecoverySucceeds() { PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class); MasterKeyActivateRepository masterKeyActivateRepository = Mockito.mock(MasterKeyActivateRepository.class); + AuthSecurityResetService authSecurityResetService = Mockito.mock(AuthSecurityResetService.class); KeyEntityRepository keyEntityRepository = Mockito.mock(KeyEntityRepository.class); MasterKeyInitProperties properties = configuredPins("MTIzNDU2Nzg=", "ODc2NTQzMjE="); + allowMasterKeyInit(masterKeyActivateRepository); MasterKeyRecoveryResult recoveryResult = new MasterKeyRecoveryResult(); recoveryResult.setLmkSeedMac(hex("1112131415161718")); Mockito.when(pcieCryptoService.recoverMasterKeyMaterial(Mockito.any())).thenReturn(recoveryResult); - LmkService service = new LmkServiceImpl(pcieCryptoService, properties, () -> { }, masterKeyActivateRepository, keyEntityRepository); + LmkService service = new LmkServiceImpl( + pcieCryptoService, + properties, + authSecurityResetService, + masterKeyActivateRepository, + keyEntityRepository + ); service.recoverKeyPackets(List.of(recoverPacketFixture(1), recoverPacketFixture(2))); - InOrder inOrder = Mockito.inOrder(pcieCryptoService, keyEntityRepository); + InOrder inOrder = Mockito.inOrder( + pcieCryptoService, + keyEntityRepository, + authSecurityResetService, + masterKeyActivateRepository + ); inOrder.verify(pcieCryptoService).recoverMasterKeyMaterial(Mockito.any()); inOrder.verify(keyEntityRepository).deleteAll(); + inOrder.verify(authSecurityResetService).resetAfterMasterKeyInitialized(); + inOrder.verify(masterKeyActivateRepository).update(Mockito.any()); } @Test