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 277e0b4d38..9facea6dde 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -273,7 +273,7 @@ public class ThingsboardInstallService { systemDataLoaderService.createSysAdmin(); systemDataLoaderService.createDefaultTenantProfiles(); systemDataLoaderService.createAdminSettings(); - systemDataLoaderService.createJwtAdminSettings(); + systemDataLoaderService.createRandomJwtSettings(); systemDataLoaderService.loadSystemWidgets(); systemDataLoaderService.createOAuth2Templates(); systemDataLoaderService.createQueues(); 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 e512fb028e..9507912c39 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 @@ -268,8 +268,13 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { } @Override - public void createJwtAdminSettings() throws Exception { - jwtSettingsService.createJwtAdminSettings(); + public void createRandomJwtSettings() throws Exception { + jwtSettingsService.createRandomJwtSettings(); + } + + @Override + public void saveLegacyYmlSettings() throws Exception { + jwtSettingsService.saveLegacyYmlSettings(); } @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 4ef8241a3b..041351f5e4 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 @@ -23,7 +23,9 @@ public interface SystemDataLoaderService { void createAdminSettings() throws Exception; - void createJwtAdminSettings() throws Exception; + void createRandomJwtSettings() throws Exception; + + void saveLegacyYmlSettings() throws Exception; void createOAuth2Templates() throws Exception; diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java index 0b8045e20a..ee34bd7f23 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java @@ -186,7 +186,7 @@ public class DefaultDataUpdateService implements DataUpdateService { break; case "3.4.1": log.info("Updating data from version 3.4.1 to 3.4.2 ..."); - systemDataLoaderService.createJwtAdminSettings(); + systemDataLoaderService.saveLegacyYmlSettings(); boolean skipAuditLogsMigration = getEnv("TB_SKIP_AUDIT_LOGS_MIGRATION", false); if (!skipAuditLogsMigration) { log.info("Starting audit logs migration. Can be skipped with TB_SKIP_AUDIT_LOGS_MIGRATION env variable set to true"); diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsServiceDefault.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java similarity index 72% rename from application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsServiceDefault.java rename to application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java index d5e92554f9..01f1deecbf 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsServiceDefault.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsService.java @@ -15,14 +15,11 @@ */ package org.thingsboard.server.service.security.auth.jwt.settings; -import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; -import org.springframework.core.env.Environment; -import org.springframework.core.env.Profiles; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cluster.TbClusterService; @@ -44,16 +41,14 @@ import static org.thingsboard.server.service.security.auth.jwt.settings.JwtSetti @Service @RequiredArgsConstructor @Slf4j -public class JwtSettingsServiceDefault implements JwtSettingsService { +public class DefaultJwtSettingsService implements JwtSettingsService { @Lazy private final AdminSettingsService adminSettingsService; @Lazy private final Optional tbClusterService; private final JwtSettingsValidator jwtSettingsValidator; - private final Environment environment; - @Getter - private final JwtSettings jwtSettings = new JwtSettings(); + private volatile JwtSettings jwtSettings = null; //lazy init @Value("${install.upgrade:false}") private boolean isUpgrade; @@ -68,21 +63,7 @@ public class JwtSettingsServiceDefault implements JwtSettingsService { @PostConstruct public void init() { - jwtSettings.setTokenExpirationTime(this.tokenExpirationTime); - jwtSettings.setRefreshTokenExpTime(this.refreshTokenExpTime); - jwtSettings.setTokenIssuer(this.tokenIssuer); - jwtSettings.setTokenSigningKey(this.tokenSigningKey); - if (!isFirstInstall()) { - reloadJwtSettings(); - } - } - private boolean isInstall() { - return environment.acceptsProfiles(Profiles.of("install")); - } - - private boolean isFirstInstall() { - return isInstall() && !isUpgrade; } @Override @@ -90,11 +71,9 @@ public class JwtSettingsServiceDefault implements JwtSettingsService { AdminSettings adminJwtSettings = findJwtAdminSettings(); if (adminJwtSettings != null) { log.info("Reloading the JWT admin settings from database"); - JwtSettings jwtLoaded = mapAdminToJwtSettings(adminJwtSettings); - jwtSettings.setTokenExpirationTime(jwtLoaded.getTokenExpirationTime()); - jwtSettings.setRefreshTokenExpTime(jwtLoaded.getRefreshTokenExpTime()); - jwtSettings.setTokenIssuer(jwtLoaded.getTokenIssuer()); - jwtSettings.setTokenSigningKey(jwtLoaded.getTokenSigningKey()); + synchronized (this) { + this.jwtSettings = mapAdminToJwtSettings(adminJwtSettings); + } } if (hasDefaultTokenSigningKey()) { @@ -119,23 +98,34 @@ public class JwtSettingsServiceDefault implements JwtSettingsService { } boolean hasDefaultTokenSigningKey() { - return TOKEN_SIGNING_KEY_DEFAULT.equals(jwtSettings.getTokenSigningKey()); + return TOKEN_SIGNING_KEY_DEFAULT.equals(getJwtSettings().getTokenSigningKey()); } /** - * Create JWT admin settings is intended to be called from Install or Upgrade scripts + * Create JWT admin settings is intended to be called from Install scripts only * */ @Override - public void createJwtAdminSettings() { + public void createRandomJwtSettings() { log.info("Creating JWT admin settings..."); - Objects.requireNonNull(jwtSettings, "JWT settings is null"); + Objects.requireNonNull(getJwtSettings(), "JWT settings is null"); + + if (hasDefaultTokenSigningKey()) { + log.info("JWT token signing key is default. Generating a new random key"); + getJwtSettings().setTokenSigningKey(Base64.getEncoder().encodeToString( + RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); + } + saveJwtSettings(getJwtSettings()); + } + + /** + * Create JWT admin settings is intended to be called from Upgrade scripts only + * */ + @Override + public void saveLegacyYmlSettings() { + log.info("Saving legacy JWT admin settings from YML..."); + Objects.requireNonNull(getJwtSettings(), "JWT settings is null"); if (isJwtAdminSettingsNotExists()) { - if (hasDefaultTokenSigningKey() && isFirstInstall()) { - log.info("JWT token signing key is default. Generating a new random key"); - jwtSettings.setTokenSigningKey(Base64.getEncoder().encodeToString( - RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); - } - saveJwtSettings(jwtSettings); + saveJwtSettings(getJwtSettings()); } } @@ -151,9 +141,7 @@ public class JwtSettingsServiceDefault implements JwtSettingsService { log.info("Saving new JWT admin settings. From this moment, the JWT parameters from YAML and ENV will be ignored"); adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminJwtSettings); - if (!isInstall()) { - tbClusterService.orElseThrow().broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, ComponentLifecycleEvent.UPDATED); - } + tbClusterService.ifPresent(cs -> cs.broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, ComponentLifecycleEvent.UPDATED)); reloadJwtSettings(); return getJwtSettings(); } @@ -166,4 +154,15 @@ public class JwtSettingsServiceDefault implements JwtSettingsService { return adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, ADMIN_SETTINGS_JWT_KEY); } + public JwtSettings getJwtSettings() { + if (this.jwtSettings == null) { + synchronized (this) { + if (this.jwtSettings == null) { + this.jwtSettings = new JwtSettings(this.tokenExpirationTime, this.refreshTokenExpTime, this.tokenIssuer, this.tokenSigningKey); + reloadJwtSettings(); + } + } + } + return this.jwtSettings; + } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorDefault.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsValidator.java similarity index 98% rename from application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorDefault.java rename to application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsValidator.java index 2ebe4e8025..ef0e88753c 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorDefault.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/DefaultJwtSettingsValidator.java @@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit; @Component @RequiredArgsConstructor -public class JwtSettingsValidatorDefault implements JwtSettingsValidator { +public class DefaultJwtSettingsValidator implements JwtSettingsValidator { @Override public void validate(JwtSettings jwtSettings) { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorInstall.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/InstallJwtSettingsValidator.java similarity index 94% rename from application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorInstall.java rename to application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/InstallJwtSettingsValidator.java index a7d097ee39..b8667c45a8 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsValidatorInstall.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/InstallJwtSettingsValidator.java @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.security.model.JwtSettings; @Profile("install") @Component @RequiredArgsConstructor -public class JwtSettingsValidatorInstall implements JwtSettingsValidator { +public class InstallJwtSettingsValidator implements JwtSettingsValidator { /** * During Install or upgrade the validation is suppressed to keep existing data diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsService.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsService.java index 0282e64804..f5858b7694 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/settings/JwtSettingsService.java @@ -23,7 +23,9 @@ public interface JwtSettingsService { void reloadJwtSettings(); - void createJwtAdminSettings(); + void createRandomJwtSettings(); + + void saveLegacyYmlSettings(); JwtSettings saveJwtSettings(JwtSettings jwtSettings);