From 29a8c930a9b9e99a22f3dc61abfa82329ab29090 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 27 May 2024 21:05:21 +0200 Subject: [PATCH] added upgrade script for update mobile secretApp --- .../install/ThingsboardInstallService.java | 2 +- .../DefaultSystemDataLoaderService.java | 52 +++++++++++++------ .../install/SystemDataLoaderService.java | 2 +- .../settings/DefaultJwtSettingsService.java | 6 +-- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 33e2ddee01..4bef0d420a 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -136,7 +136,7 @@ public class ThingsboardInstallService { dataUpdateService.updateData("3.6.4"); entityDatabaseSchemaService.createCustomerTitleUniqueConstraintIfNotExists(); systemDataLoaderService.updateDefaultNotificationConfigs(false); - systemDataLoaderService.updateJwtSettings(); + systemDataLoaderService.updateSecuritySettings(); //TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache break; default: diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index bdd0494443..1fcdbef3a2 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -26,6 +26,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -68,6 +69,7 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.BooleanDataEntry; import org.thingsboard.server.common.data.kv.DoubleDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.oauth2.OAuth2Mobile; import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.query.BooleanFilterPredicate; @@ -98,6 +100,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.notification.NotificationTargetService; +import org.thingsboard.server.dao.oauth2.OAuth2MobileDao; import org.thingsboard.server.dao.queue.QueueService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.settings.AdminSettingsService; @@ -120,7 +123,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.thingsboard.server.common.data.DataConstants.DEFAULT_DEVICE_TYPE; import static org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService.isSigningKeyDefault; -import static org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService.validateTokenSigningKeyLength; +import static org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService.validateKeyLength; @Service @Profile("install") @@ -146,6 +149,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { private final DeviceConnectivityConfiguration connectivityConfiguration; private final QueueService queueService; private final JwtSettingsService jwtSettingsService; + private final OAuth2MobileDao oAuth2MobileDao; private final NotificationSettingsService notificationSettingsService; private final NotificationTargetService notificationTargetService; @@ -269,21 +273,21 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @Override public void createRandomJwtSettings() throws Exception { - if (jwtSettingsService.getJwtSettings() == null) { - log.info("Creating JWT admin settings..."); - var jwtSettings = new JwtSettings(this.tokenExpirationTime, this.refreshTokenExpTime, this.tokenIssuer, this.tokenSigningKey); - if (isSigningKeyDefault(jwtSettings) || !validateTokenSigningKeyLength(jwtSettings)) { - jwtSettings.setTokenSigningKey(Base64.getEncoder().encodeToString( - RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); - } - jwtSettingsService.saveJwtSettings(jwtSettings); - } else { - log.info("Skip creating JWT admin settings because they already exist."); + if (jwtSettingsService.getJwtSettings() == null) { + log.info("Creating JWT admin settings..."); + var jwtSettings = new JwtSettings(this.tokenExpirationTime, this.refreshTokenExpTime, this.tokenIssuer, this.tokenSigningKey); + if (isSigningKeyDefault(jwtSettings) || !validateKeyLength(jwtSettings.getTokenSigningKey())) { + jwtSettings.setTokenSigningKey(Base64.getEncoder().encodeToString( + RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); } + jwtSettingsService.saveJwtSettings(jwtSettings); + } else { + log.info("Skip creating JWT admin settings because they already exist."); + } } @Override - public void updateJwtSettings() { + public void updateSecuritySettings() { JwtSettings jwtSettings = jwtSettingsService.getJwtSettings(); boolean invalidSignKey = false; String warningMessage = null; @@ -291,7 +295,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { if (isSigningKeyDefault(jwtSettings)) { warningMessage = "The platform is using the default JWT Signing Key, which is a security risk."; invalidSignKey = true; - } else if (!validateTokenSigningKeyLength(jwtSettings)) { + } else if (!validateKeyLength(jwtSettings.getTokenSigningKey())) { warningMessage = "The JWT Signing Key is shorter than 512 bits, which is a security risk."; invalidSignKey = true; } @@ -301,10 +305,28 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { "You can change the JWT Signing Key using the Web UI: " + "Navigate to \"System settings -> Security settings\" while logged in as a System Administrator.", warningMessage); - jwtSettings.setTokenSigningKey(Base64.getEncoder().encodeToString( - RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); + jwtSettings.setTokenSigningKey(generateRandomKey()); jwtSettingsService.saveJwtSettings(jwtSettings); } + + List mobiles = oAuth2MobileDao.find(TenantId.SYS_TENANT_ID); + if (CollectionUtils.isNotEmpty(mobiles)) { + mobiles.stream() + .filter(config -> !validateKeyLength(config.getAppSecret())) + .forEach(config -> { + log.warn("WARNING: The App secret is shorter than 512 bits, which is a security risk. " + + "A new Application Secret has been added automatically for Mobile Application [{}]. " + + "You can change the Application Secret using the Web UI: " + + "Navigate to \"Security settings -> OAuth2 -> Mobile applications\" while logged in as a System Administrator.", config.getPkgName()); + config.setAppSecret(generateRandomKey()); + oAuth2MobileDao.save(TenantId.SYS_TENANT_ID, config); + }); + } + } + + private String generateRandomKey() { + return Base64.getEncoder().encodeToString( + RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8)); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java index 71c829ee11..2f4b5fa885 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java @@ -25,7 +25,7 @@ public interface SystemDataLoaderService { void createRandomJwtSettings() throws Exception; - void updateJwtSettings() throws Exception; + void updateSecuritySettings() throws Exception; void createOAuth2Templates() throws Exception; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java index c5c04ac312..aba7c5b930 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java @@ -17,8 +17,6 @@ package org.thingsboard.server.service.security.auth.jwt.settings; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cluster.TbClusterService; @@ -111,8 +109,8 @@ public class DefaultJwtSettingsService implements JwtSettingsService { return TOKEN_SIGNING_KEY_DEFAULT.equals(settings.getTokenSigningKey()); } - public static boolean validateTokenSigningKeyLength(JwtSettings settings) { - return Base64.getDecoder().decode(settings.getTokenSigningKey()).length * Byte.SIZE >= KEY_LENGTH; + public static boolean validateKeyLength(String key) { + return Base64.getDecoder().decode(key).length * Byte.SIZE >= KEY_LENGTH; } }