Jwt settings refactored after review

This commit is contained in:
Sergey Matvienko 2022-11-16 18:36:05 +01:00
parent 4d97b355d3
commit bb261b3401
8 changed files with 55 additions and 47 deletions

View File

@ -273,7 +273,7 @@ public class ThingsboardInstallService {
systemDataLoaderService.createSysAdmin(); systemDataLoaderService.createSysAdmin();
systemDataLoaderService.createDefaultTenantProfiles(); systemDataLoaderService.createDefaultTenantProfiles();
systemDataLoaderService.createAdminSettings(); systemDataLoaderService.createAdminSettings();
systemDataLoaderService.createJwtAdminSettings(); systemDataLoaderService.createRandomJwtSettings();
systemDataLoaderService.loadSystemWidgets(); systemDataLoaderService.loadSystemWidgets();
systemDataLoaderService.createOAuth2Templates(); systemDataLoaderService.createOAuth2Templates();
systemDataLoaderService.createQueues(); systemDataLoaderService.createQueues();

View File

@ -268,8 +268,13 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
} }
@Override @Override
public void createJwtAdminSettings() throws Exception { public void createRandomJwtSettings() throws Exception {
jwtSettingsService.createJwtAdminSettings(); jwtSettingsService.createRandomJwtSettings();
}
@Override
public void saveLegacyYmlSettings() throws Exception {
jwtSettingsService.saveLegacyYmlSettings();
} }
@Override @Override

View File

@ -23,7 +23,9 @@ public interface SystemDataLoaderService {
void createAdminSettings() throws Exception; void createAdminSettings() throws Exception;
void createJwtAdminSettings() throws Exception; void createRandomJwtSettings() throws Exception;
void saveLegacyYmlSettings() throws Exception;
void createOAuth2Templates() throws Exception; void createOAuth2Templates() throws Exception;

View File

@ -186,7 +186,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
break; break;
case "3.4.1": case "3.4.1":
log.info("Updating data from version 3.4.1 to 3.4.2 ..."); 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); boolean skipAuditLogsMigration = getEnv("TB_SKIP_AUDIT_LOGS_MIGRATION", false);
if (!skipAuditLogsMigration) { if (!skipAuditLogsMigration) {
log.info("Starting audit logs migration. Can be skipped with TB_SKIP_AUDIT_LOGS_MIGRATION env variable set to true"); log.info("Starting audit logs migration. Can be skipped with TB_SKIP_AUDIT_LOGS_MIGRATION env variable set to true");

View File

@ -15,14 +15,11 @@
*/ */
package org.thingsboard.server.service.security.auth.jwt.settings; package org.thingsboard.server.service.security.auth.jwt.settings;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy; 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.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
@ -44,16 +41,14 @@ import static org.thingsboard.server.service.security.auth.jwt.settings.JwtSetti
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j @Slf4j
public class JwtSettingsServiceDefault implements JwtSettingsService { public class DefaultJwtSettingsService implements JwtSettingsService {
@Lazy @Lazy
private final AdminSettingsService adminSettingsService; private final AdminSettingsService adminSettingsService;
@Lazy @Lazy
private final Optional<TbClusterService> tbClusterService; private final Optional<TbClusterService> tbClusterService;
private final JwtSettingsValidator jwtSettingsValidator; private final JwtSettingsValidator jwtSettingsValidator;
private final Environment environment; private volatile JwtSettings jwtSettings = null; //lazy init
@Getter
private final JwtSettings jwtSettings = new JwtSettings();
@Value("${install.upgrade:false}") @Value("${install.upgrade:false}")
private boolean isUpgrade; private boolean isUpgrade;
@ -68,21 +63,7 @@ public class JwtSettingsServiceDefault implements JwtSettingsService {
@PostConstruct @PostConstruct
public void init() { 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 @Override
@ -90,11 +71,9 @@ public class JwtSettingsServiceDefault implements JwtSettingsService {
AdminSettings adminJwtSettings = findJwtAdminSettings(); AdminSettings adminJwtSettings = findJwtAdminSettings();
if (adminJwtSettings != null) { if (adminJwtSettings != null) {
log.info("Reloading the JWT admin settings from database"); log.info("Reloading the JWT admin settings from database");
JwtSettings jwtLoaded = mapAdminToJwtSettings(adminJwtSettings); synchronized (this) {
jwtSettings.setTokenExpirationTime(jwtLoaded.getTokenExpirationTime()); this.jwtSettings = mapAdminToJwtSettings(adminJwtSettings);
jwtSettings.setRefreshTokenExpTime(jwtLoaded.getRefreshTokenExpTime()); }
jwtSettings.setTokenIssuer(jwtLoaded.getTokenIssuer());
jwtSettings.setTokenSigningKey(jwtLoaded.getTokenSigningKey());
} }
if (hasDefaultTokenSigningKey()) { if (hasDefaultTokenSigningKey()) {
@ -119,23 +98,34 @@ public class JwtSettingsServiceDefault implements JwtSettingsService {
} }
boolean hasDefaultTokenSigningKey() { 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 @Override
public void createJwtAdminSettings() { public void createRandomJwtSettings() {
log.info("Creating JWT admin settings..."); log.info("Creating JWT admin settings...");
Objects.requireNonNull(jwtSettings, "JWT settings is null"); Objects.requireNonNull(getJwtSettings(), "JWT settings is null");
if (isJwtAdminSettingsNotExists()) {
if (hasDefaultTokenSigningKey() && isFirstInstall()) { if (hasDefaultTokenSigningKey()) {
log.info("JWT token signing key is default. Generating a new random key"); log.info("JWT token signing key is default. Generating a new random key");
jwtSettings.setTokenSigningKey(Base64.getEncoder().encodeToString( getJwtSettings().setTokenSigningKey(Base64.getEncoder().encodeToString(
RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8))); RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8)));
} }
saveJwtSettings(jwtSettings); 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()) {
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"); 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); adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminJwtSettings);
if (!isInstall()) { tbClusterService.ifPresent(cs -> cs.broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, ComponentLifecycleEvent.UPDATED));
tbClusterService.orElseThrow().broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, TenantId.SYS_TENANT_ID, ComponentLifecycleEvent.UPDATED);
}
reloadJwtSettings(); reloadJwtSettings();
return getJwtSettings(); return getJwtSettings();
} }
@ -166,4 +154,15 @@ public class JwtSettingsServiceDefault implements JwtSettingsService {
return adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, ADMIN_SETTINGS_JWT_KEY); 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;
}
} }

View File

@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class JwtSettingsValidatorDefault implements JwtSettingsValidator { public class DefaultJwtSettingsValidator implements JwtSettingsValidator {
@Override @Override
public void validate(JwtSettings jwtSettings) { public void validate(JwtSettings jwtSettings) {

View File

@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.security.model.JwtSettings;
@Profile("install") @Profile("install")
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class JwtSettingsValidatorInstall implements JwtSettingsValidator { public class InstallJwtSettingsValidator implements JwtSettingsValidator {
/** /**
* During Install or upgrade the validation is suppressed to keep existing data * During Install or upgrade the validation is suppressed to keep existing data

View File

@ -23,7 +23,9 @@ public interface JwtSettingsService {
void reloadJwtSettings(); void reloadJwtSettings();
void createJwtAdminSettings(); void createRandomJwtSettings();
void saveLegacyYmlSettings();
JwtSettings saveJwtSettings(JwtSettings jwtSettings); JwtSettings saveJwtSettings(JwtSettings jwtSettings);