@ -19,13 +19,17 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.util.concurrent.FutureCallback ;
import com.google.common.util.concurrent.Futures ;
import com.google.common.util.concurrent.ListenableFuture ;
import jakarta.annotation.Nullable ;
import jakarta.annotation.PostConstruct ;
import jakarta.annotation.PreDestroy ;
import lombok.Getter ;
import lombok.RequiredArgsConstructor ;
import lombok.SneakyThrows ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.lang3.RandomStringUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Value ;
import org.springframework.context.annotation.Bean ;
import org.springframework.context.annotation.Lazy ;
import org.springframework.context.annotation.Profile ;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder ;
import org.springframework.stereotype.Service ;
@ -81,6 +85,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.security.Authority ;
import org.thingsboard.server.common.data.security.DeviceCredentials ;
import org.thingsboard.server.common.data.security.UserCredentials ;
import org.thingsboard.server.common.data.security.model.JwtSettings ;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration ;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData ;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration ;
@ -100,14 +105,11 @@ import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService ;
import org.thingsboard.server.dao.timeseries.TimeseriesService ;
import org.thingsboard.server.dao.user.UserService ;
import org.thingsboard.server.dao.widget.WidgetTypeService ;
import org.thingsboard.server.dao.widget.WidgetsBundleService ;
import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService ;
import jakarta.annotation.Nullable ;
import jakarta.annotation.PostConstruct ;
import jakarta.annotation.PreDestroy ;
import java.nio.charset.StandardCharsets ;
import java.util.Arrays ;
import java.util.Base64 ;
import java.util.Collections ;
import java.util.List ;
import java.util.TreeMap ;
@ -117,79 +119,51 @@ import java.util.concurrent.TimeUnit;
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 ;
@Service
@Profile ( "install" )
@Slf4j
@RequiredArgsConstructor
public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
public static final String CUSTOMER_CRED = "customer" ;
public static final String ACTIVITY_STATE = "active" ;
@Autowired
private InstallScripts installScripts ;
private final InstallScripts installScripts ;
private final UserService userService ;
private final AdminSettingsService adminSettingsService ;
private final TenantService tenantService ;
private final TenantProfileService tenantProfileService ;
private final CustomerService customerService ;
private final DeviceService deviceService ;
private final DeviceProfileService deviceProfileService ;
private final AttributesService attributesService ;
private final DeviceCredentialsService deviceCredentialsService ;
private final RuleChainService ruleChainService ;
private final TimeseriesService tsService ;
private final DeviceConnectivityConfiguration connectivityConfiguration ;
private final QueueService queueService ;
private final JwtSettingsService jwtSettingsService ;
private final NotificationSettingsService notificationSettingsService ;
private final NotificationTargetService notificationTargetService ;
@Autowired
private BCryptPasswordEncoder passwordEncoder ;
@Autowired
private UserService userService ;
@Autowired
private AdminSettingsService adminSettingsService ;
@Autowired
private WidgetTypeService widgetTypeService ;
@Autowired
private WidgetsBundleService widgetsBundleService ;
@Autowired
private TenantService tenantService ;
@Autowired
private TenantProfileService tenantProfileService ;
@Autowired
private CustomerService customerService ;
@Autowired
private DeviceService deviceService ;
@Autowired
private DeviceProfileService deviceProfileService ;
@Autowired
private AttributesService attributesService ;
@Autowired
private DeviceCredentialsService deviceCredentialsService ;
@Autowired
private RuleChainService ruleChainService ;
@Autowired
private TimeseriesService tsService ;
@Autowired
private DeviceConnectivityConfiguration connectivityConfiguration ;
@Value ( "${state.persistToTelemetry:false}" )
@Getter
private boolean persistActivityToTelemetry ;
@Lazy
@Autowired
private QueueService queueService ;
@Autowired
private JwtSettingsService jwtSettingsService ;
@Autowired
private NotificationSettingsService notificationSettingsService ;
@Autowired
private NotificationTargetService notificationTargetService ;
@Value ( "${security.jwt.tokenExpirationTime:9000}" )
private Integer tokenExpirationTime ;
@Value ( "${security.jwt.refreshTokenExpTime:604800}" )
private Integer refreshTokenExpTime ;
@Value ( "${security.jwt.tokenIssuer:thingsboard.io}" )
private String tokenIssuer ;
@Value ( "${security.jwt.tokenSigningKey:thingsboardDefaultSigningKey}" )
private String tokenSigningKey ;
@Bean
protected BCryptPasswordEncoder passwordEncoder ( ) {
@ -295,7 +269,42 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Override
public void createRandomJwtSettings ( ) throws Exception {
jwtSettingsService . createRandomJwtSettings ( ) ;
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." ) ;
}
}
@Override
public void updateJwtSettings ( ) {
JwtSettings jwtSettings = jwtSettingsService . getJwtSettings ( ) ;
boolean invalidSignKey = false ;
String warningMessage = null ;
if ( isSigningKeyDefault ( jwtSettings ) ) {
warningMessage = "The platform is using the default JWT Signing Key, which is a security risk." ;
invalidSignKey = true ;
} else if ( ! validateTokenSigningKeyLength ( jwtSettings ) ) {
warningMessage = "The JWT Signing Key is shorter than 512 bits, which is a security risk." ;
invalidSignKey = true ;
}
if ( invalidSignKey ) {
log . warn ( "WARNING: {}. A new JWT Signing Key has been added automatically. " +
"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 ) ) ) ;
jwtSettingsService . saveJwtSettings ( jwtSettings ) ;
}
}
@Override