From 128c28956abc8c6c1a98fea68c56456f91092046 Mon Sep 17 00:00:00 2001 From: gatsby068 <133197656+gatsby068@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:12:15 +0800 Subject: [PATCH] Update Network Secret Key (#19) * Update Network Secret Key * modify test units --- VERSION | 2 +- .../services/basic/AppConfiguration.java | 42 +++++++++++++++++++ .../registry/entity/RegistryBoxEntity.java | 3 ++ .../RegistryBoxEntityRepository.java | 13 ++++++ .../registry/service/RegistryService.java | 29 +++++++++---- .../migration/V2.0.0__BoxRegistry_Update.sql | 15 +++++++ .../registry/rest/RegistryResourceTest.java | 25 +++++++++-- 7 files changed, 115 insertions(+), 14 deletions(-) create mode 100644 eulixplatform-registry/src/main/resources/profiles/community/db/migration/V2.0.0__BoxRegistry_Update.sql diff --git a/VERSION b/VERSION index bd8bf882..227cea21 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.7.0 +2.0.0 diff --git a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/basic/AppConfiguration.java b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/basic/AppConfiguration.java index e59d18ef..ffc0554e 100644 --- a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/basic/AppConfiguration.java +++ b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/basic/AppConfiguration.java @@ -17,19 +17,61 @@ package xyz.eulix.platform.services.basic; import io.quarkus.runtime.Startup; +import org.apache.commons.codec.digest.DigestUtils; import org.jboss.logging.Logger; +import xyz.eulix.platform.common.support.CommonUtils; +import xyz.eulix.platform.services.registry.entity.RegistryBoxEntity; +import xyz.eulix.platform.services.registry.repository.RegistryBoxEntityRepository; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; @Startup @ApplicationScoped public class AppConfiguration { private static final Logger LOG = Logger.getLogger("app.log"); + @Inject + RegistryBoxEntityRepository registryBoxEntityRepository; + @PostConstruct void init() { LOG.infov("Application init begin..."); + + /* + * 更新 network secret 为 hash结果 + * 适用版本:2.0.0 + */ + LOG.infov("Update Network Secret Key begin..."); + // 查询全部已注册盒子 + AtomicInteger successBoxCount = new AtomicInteger(0); + AtomicInteger failureBoxCount = new AtomicInteger(0); + List registryBoxEntityList = registryBoxEntityRepository.listAll(); + registryBoxEntityList.stream() + .filter(registryBoxEntity -> CommonUtils.isNullOrEmpty(registryBoxEntity.getNetworkSecretSalt())) + .forEach(registryBoxEntity -> { + // 为已注册盒子生成盐值,并重新计算secret key + try { + // 随机字符串做盐 + String salt = CommonUtils.getUUID(); + String secretKey = registryBoxEntity.getNetworkSecretKey(); + // 盐和密码结合取hash值 + String hashSecretKey = DigestUtils.md5Hex(salt + secretKey); + registryBoxEntityRepository.updateSecretKeyAndSaltByBoxUUID(hashSecretKey, salt, registryBoxEntity.getBoxUUID()); + LOG.infov("Update Network Secret Key success, boxuuid:{0}, from:{1} ,to:{2}", registryBoxEntity.getBoxUUID(), + secretKey, hashSecretKey); + successBoxCount.incrementAndGet(); + } catch (Exception e) { + LOG.errorv(e, "Update Network Secret Key failed, boxuuid:{0}", registryBoxEntity.getBoxUUID()); + failureBoxCount.incrementAndGet(); + } + }); + + LOG.infov("Update Network Secret Key success! Total:{0}, success:{1}, failure:{2}", registryBoxEntityList.size(), + successBoxCount.get(), failureBoxCount.get()); LOG.infov("Application init succeed!"); } } diff --git a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/entity/RegistryBoxEntity.java b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/entity/RegistryBoxEntity.java index e61a3ca0..938a4996 100644 --- a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/entity/RegistryBoxEntity.java +++ b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/entity/RegistryBoxEntity.java @@ -44,4 +44,7 @@ public class RegistryBoxEntity extends BaseEntity { @Column(name = "network_secret_key") private String networkSecretKey; + + @Column(name = "network_secret_salt") + private String networkSecretSalt; } diff --git a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/repository/RegistryBoxEntityRepository.java b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/repository/RegistryBoxEntityRepository.java index dd9ac548..c355272c 100644 --- a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/repository/RegistryBoxEntityRepository.java +++ b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/repository/RegistryBoxEntityRepository.java @@ -20,6 +20,7 @@ import xyz.eulix.platform.services.registry.entity.RegistryBoxEntity; import javax.enterprise.context.ApplicationScoped; +import javax.transaction.Transactional; import java.util.List; import java.util.Optional; @@ -41,6 +42,9 @@ public class RegistryBoxEntityRepository implements PanacheRepository findByBoxUUID(String boxUUID) { return this.find(FIND_BY_BOXUUID, boxUUID).firstResultOptional(); } @@ -56,4 +60,13 @@ public Optional findByClientIdAndSecretKey(String clientId, S public List findByBoxUUIDs(List boxUUIDs) { return this.find(FIND_BY_BOXUUIDS, boxUUIDs).list(); } + + public Optional findByClientId(String networkClientId) { + return this.find(FIND_BY_CLIENTID, networkClientId).firstResultOptional(); + } + + @Transactional + public void updateSecretKeyAndSaltByBoxUUID(String hashSecretKey, String salt, String boxUUID) { + update("set network_secret_key=?1, network_secret_salt=?2, updated_at=now() where box_uuid=?3 ", hashSecretKey, salt, boxUUID); + } } diff --git a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/service/RegistryService.java b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/service/RegistryService.java index 881d8856..09e48cc5 100644 --- a/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/service/RegistryService.java +++ b/eulixplatform-registry/src/main/java/xyz/eulix/platform/services/registry/service/RegistryService.java @@ -17,6 +17,7 @@ package xyz.eulix.platform.services.registry.service; import io.quarkus.hibernate.orm.panache.PanacheQuery; +import org.apache.commons.codec.digest.DigestUtils; import org.jboss.logging.Logger; import xyz.eulix.platform.services.config.ApplicationProperties; import xyz.eulix.platform.services.network.service.NetworkService; @@ -130,15 +131,15 @@ public void deleteClientByClientUUID(String boxUUID, String userId, String clien public BoxRegistryResult registryBox (BoxTokenEntity boxToken, String networkClientId) { var registryBoxEntity = boxEntityRepository.findByBoxUUID(boxToken.getBoxUUID()); if (registryBoxEntity.isPresent()) { - return BoxRegistryResult.of( - registryBoxEntity.get().getBoxUUID(), - NetworkClient.of(registryBoxEntity.get().getNetworkClientId(), registryBoxEntity.get().getNetworkSecretKey())); + LOG.warnv("box uuid had already registered, boxuuid:{0}", boxToken.getBoxUUID()); + throw new WebApplicationException("box uuid had already registered. Pls reset and try again.", Response.Status.NOT_ACCEPTABLE); } // 注册box - RegistryBoxEntity boxEntity = registryBox(boxToken.getBoxUUID(), boxToken.getBoxRegKey(), networkClientId); + String networkClientSecret = "nrk_" + CommonUtils.createUnifiedRandomCharacters(10); + RegistryBoxEntity boxEntity = registryBox(boxToken.getBoxUUID(), boxToken.getBoxRegKey(), networkClientId, networkClientSecret); // 计算路由 networkService.calculateNetworkRoute(boxEntity.getNetworkClientId()); - return BoxRegistryResult.of(boxEntity.getBoxUUID(), NetworkClient.of(boxEntity.getNetworkClientId(), boxEntity.getNetworkSecretKey())); + return BoxRegistryResult.of(boxEntity.getBoxUUID(), NetworkClient.of(boxEntity.getNetworkClientId(), networkClientSecret)); } @Transactional @@ -179,7 +180,7 @@ public UserRegistryResult registryUser (UserRegistryInfo userRegistryInfo, Strin } @Transactional - public RegistryBoxEntity registryBox(String boxUUID, String boxRegKey, String networkClientId) { + public RegistryBoxEntity registryBox(String boxUUID, String boxRegKey, String networkClientId, String networkSecretKey) { // 注册box RegistryBoxEntity boxEntity = new RegistryBoxEntity(); { @@ -187,7 +188,11 @@ public RegistryBoxEntity registryBox(String boxUUID, String boxRegKey, String ne boxEntity.setBoxRegKey(boxRegKey); // network client boxEntity.setNetworkClientId(CommonUtils.isNullOrBlank(networkClientId) ? CommonUtils.getUUID() : networkClientId); - boxEntity.setNetworkSecretKey("nrk_" + CommonUtils.createUnifiedRandomCharacters(10)); + // 随机字符串做盐 + String salt = CommonUtils.getUUID(); + // 盐和密码结合取hash值 + boxEntity.setNetworkSecretSalt(salt); + boxEntity.setNetworkSecretKey(DigestUtils.md5Hex(salt + networkSecretKey)); } boxEntityRepository.persist(boxEntity); return boxEntity; @@ -544,11 +549,17 @@ public void reachUpperLimit(String boxUUID) { } public Boolean networkClientAuth(String clientId, String secretKey) { - Optional registryBoxEntityOp = boxEntityRepository.findByClientIdAndSecretKey(clientId, secretKey); + Optional registryBoxEntityOp = boxEntityRepository.findByClientId(clientId); if (registryBoxEntityOp.isEmpty()) { + LOG.infov("network client is empty, client id:{0}, secret key:{1}", clientId, secretKey); + return false; + } + String salt = registryBoxEntityOp.get().getNetworkSecretSalt(); + if (!registryBoxEntityOp.get().getNetworkSecretKey().equals(DigestUtils.md5Hex(salt + secretKey))) { LOG.infov("network client auth failed, client id:{0}, secret key:{1}", clientId, secretKey); + return false; } - return registryBoxEntityOp.isPresent(); + return true; } public BoxRegistryDetailInfo boxRegistryBindUserAndClientInfo(String uuid) { diff --git a/eulixplatform-registry/src/main/resources/profiles/community/db/migration/V2.0.0__BoxRegistry_Update.sql b/eulixplatform-registry/src/main/resources/profiles/community/db/migration/V2.0.0__BoxRegistry_Update.sql new file mode 100644 index 00000000..8a616354 --- /dev/null +++ b/eulixplatform-registry/src/main/resources/profiles/community/db/migration/V2.0.0__BoxRegistry_Update.sql @@ -0,0 +1,15 @@ +-- Copyright (c) 2022 Institute of Software Chinese Academy of Sciences (ISCAS) +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +ALTER TABLE box_registries ADD network_secret_salt VARCHAR(128) DEFAULT NULL COMMENT 'network client访问密钥盐值'; \ No newline at end of file diff --git a/eulixplatform-registry/src/test/java/xyz/eulix/platform/services/registry/rest/RegistryResourceTest.java b/eulixplatform-registry/src/test/java/xyz/eulix/platform/services/registry/rest/RegistryResourceTest.java index f5532846..fad7f4a4 100644 --- a/eulixplatform-registry/src/test/java/xyz/eulix/platform/services/registry/rest/RegistryResourceTest.java +++ b/eulixplatform-registry/src/test/java/xyz/eulix/platform/services/registry/rest/RegistryResourceTest.java @@ -72,6 +72,15 @@ void registryBox() { .body() .as(BoxRegistryResult.class); Assertions.assertNotNull(result); + + given() + .header("Request-Id", "uuid") + .header("Box-Reg-Key", "box_reg_key") + .pathParam( "box_uuid","box_uuid") + .contentType(ContentType.JSON) + .when().delete("/v2/platform/boxes/{box_uuid}") + .then() + .statusCode(204); } @Test @@ -90,16 +99,24 @@ void registryDuplicated() { .body() .as(BoxRegistryResult.class); - final BoxRegistryResult result1 = given() + final int statusCode = given() .header("Request-Id", bid + "-1") .header("Box-Reg-Key", "box_reg_key") .body(info) .contentType(ContentType.JSON) .when().post("/v2/platform/boxes") - .body() - .as(BoxRegistryResult.class); + .getStatusCode(); Assertions.assertNotNull(result); - Assertions.assertNotNull(result1); + Assertions.assertEquals(406, statusCode); + + given() + .header("Request-Id", "uuid") + .header("Box-Reg-Key", "box_reg_key") + .pathParam( "box_uuid","box_uuid") + .contentType(ContentType.JSON) + .when().delete("/v2/platform/boxes/{box_uuid}") + .then() + .statusCode(204); } @Test