Improvements for system notifications; add test
This commit is contained in:
parent
2a87f2ee7e
commit
c55ac0efc6
@ -182,7 +182,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
|
||||
NotificationRequest notificationRequest = NotificationRequest.builder()
|
||||
.tenantId(tenantId)
|
||||
.template(template)
|
||||
.targets(List.of(EntityId.NULL_UUID)) // TODO: refactor
|
||||
.targets(List.of(EntityId.NULL_UUID)) // this is temporary and will be removed when 'create from scratch' functionality is implemented for recipients
|
||||
.status(NotificationRequestStatus.PROCESSING)
|
||||
.build();
|
||||
try {
|
||||
|
||||
@ -46,7 +46,7 @@ public class DefaultJwtSettingsService implements JwtSettingsService {
|
||||
private final AdminSettingsService adminSettingsService;
|
||||
@Lazy
|
||||
private final Optional<TbClusterService> tbClusterService;
|
||||
private final NotificationCenter notificationCenter;
|
||||
private final Optional<NotificationCenter> notificationCenter;
|
||||
private final JwtSettingsValidator jwtSettingsValidator;
|
||||
|
||||
@Value("${security.jwt.tokenExpirationTime:9000}")
|
||||
@ -128,7 +128,9 @@ public class DefaultJwtSettingsService implements JwtSettingsService {
|
||||
log.warn("WARNING: The platform is configured to use default JWT Signing Key. " +
|
||||
"This is a security issue that needs to be resolved. Please change the JWT Signing Key using the Web UI. " +
|
||||
"Navigate to \"System settings -> Security settings\" while logged in as a System Administrator.");
|
||||
notificationCenter.sendGeneralWebNotification(TenantId.SYS_TENANT_ID, new SystemAdministratorsFilter(), DefaultNotifications.jwtSigningKeyIssue.toTemplate());
|
||||
notificationCenter.ifPresent(notificationCenter -> {
|
||||
notificationCenter.sendGeneralWebNotification(TenantId.SYS_TENANT_ID, new SystemAdministratorsFilter(), DefaultNotifications.jwtSigningKeyIssue.toTemplate());
|
||||
});
|
||||
}
|
||||
this.jwtSettings = result;
|
||||
}
|
||||
|
||||
@ -16,14 +16,22 @@
|
||||
package org.thingsboard.server.service.security.auth;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.rule.engine.api.NotificationCenter;
|
||||
import org.thingsboard.server.common.data.AdminSettings;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||
import org.thingsboard.server.common.data.notification.targets.platform.SystemAdministratorsFilter;
|
||||
import org.thingsboard.server.common.data.security.Authority;
|
||||
import org.thingsboard.server.common.data.security.model.JwtSettings;
|
||||
import org.thingsboard.server.common.data.security.model.JwtToken;
|
||||
import org.thingsboard.server.dao.settings.AdminSettingsService;
|
||||
import org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsService;
|
||||
import org.thingsboard.server.service.security.auth.jwt.settings.DefaultJwtSettingsValidator;
|
||||
import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.security.model.UserPrincipal;
|
||||
@ -33,28 +41,40 @@ import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.willReturn;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class JwtTokenFactoryTest {
|
||||
|
||||
private static JwtTokenFactory tokenFactory;
|
||||
private static JwtSettings jwtSettings;
|
||||
private JwtTokenFactory tokenFactory;
|
||||
private AdminSettingsService adminSettingsService;
|
||||
private NotificationCenter notificationCenter;
|
||||
private JwtSettingsService jwtSettingsService;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeAll() {
|
||||
private JwtSettings jwtSettings;
|
||||
|
||||
@Before
|
||||
public void beforeEach() {
|
||||
jwtSettings = new JwtSettings();
|
||||
jwtSettings.setTokenIssuer("tb");
|
||||
jwtSettings.setTokenSigningKey("abewafaf");
|
||||
jwtSettings.setTokenExpirationTime((int) TimeUnit.HOURS.toSeconds(2));
|
||||
jwtSettings.setRefreshTokenExpTime((int) TimeUnit.DAYS.toSeconds(7));
|
||||
|
||||
JwtSettingsService jwtSettingsService = mock(JwtSettingsService.class);
|
||||
willReturn(jwtSettings).given(jwtSettingsService).getJwtSettings();
|
||||
adminSettingsService = mock(AdminSettingsService.class);
|
||||
notificationCenter = mock(NotificationCenter.class);
|
||||
jwtSettingsService = mockJwtSettingsService();
|
||||
mockJwtSettings(jwtSettings);
|
||||
|
||||
tokenFactory = new JwtTokenFactory(jwtSettingsService);
|
||||
}
|
||||
@ -150,6 +170,33 @@ public class JwtTokenFactoryTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJwtSigningKeyIssueNotification() {
|
||||
JwtSettings badJwtSettings = jwtSettings;
|
||||
badJwtSettings.setTokenSigningKey(JwtSettingsService.TOKEN_SIGNING_KEY_DEFAULT);
|
||||
mockJwtSettings(badJwtSettings);
|
||||
jwtSettingsService = mockJwtSettingsService();
|
||||
|
||||
for (int i = 0; i < 5; i++) { // to check if notification is not sent twice
|
||||
jwtSettingsService.getJwtSettings();
|
||||
}
|
||||
verify(notificationCenter, times(1)).sendGeneralWebNotification(eq(TenantId.SYS_TENANT_ID),
|
||||
isA(SystemAdministratorsFilter.class), argThat(template -> template.getConfiguration().getDeliveryMethodsTemplates().get(NotificationDeliveryMethod.WEB)
|
||||
.getBody().contains("The platform is configured to use default JWT Signing Key")));
|
||||
}
|
||||
|
||||
private void mockJwtSettings(JwtSettings settings) {
|
||||
AdminSettings adminJwtSettings = new AdminSettings();
|
||||
adminJwtSettings.setJsonValue(JacksonUtil.valueToTree(settings));
|
||||
when(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, JwtSettingsService.ADMIN_SETTINGS_JWT_KEY))
|
||||
.thenReturn(adminJwtSettings);
|
||||
}
|
||||
|
||||
private DefaultJwtSettingsService mockJwtSettingsService() {
|
||||
return new DefaultJwtSettingsService(adminSettingsService, Optional.empty(),
|
||||
Optional.of(notificationCenter), new DefaultJwtSettingsValidator());
|
||||
}
|
||||
|
||||
private void checkExpirationTime(JwtToken jwtToken, int tokenLifetime) {
|
||||
Claims claims = tokenFactory.parseTokenClaims(jwtToken).getBody();
|
||||
assertThat(claims.getExpiration()).matches(actualExpirationTime -> {
|
||||
|
||||
@ -66,6 +66,9 @@ import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
|
||||
@RequiredArgsConstructor
|
||||
public class DefaultNotifications {
|
||||
|
||||
private static final String YELLOW_COLOR = "#F9D916";
|
||||
private static final String RED_COLOR = "#e91a1a";
|
||||
|
||||
public static final DefaultNotification maintenanceWork = DefaultNotification.builder()
|
||||
.name("Maintenance work notification")
|
||||
.subject("Infrastructure maintenance")
|
||||
@ -77,7 +80,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.ENTITIES_LIMIT)
|
||||
.subject("${entityType}s limit will be reached soon for tenant ${tenantName}")
|
||||
.text("${entityType}s usage: ${currentCount}/${limit} (${percents}%)")
|
||||
.icon("warning").color("#F9D916")
|
||||
.icon("warning").color(YELLOW_COLOR)
|
||||
.rule(DefaultRule.builder()
|
||||
.name("Entities count limit (sysadmin)")
|
||||
.triggerConfig(EntitiesLimitNotificationRuleTriggerConfig.builder()
|
||||
@ -100,7 +103,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.API_USAGE_LIMIT)
|
||||
.subject("${feature} feature will be disabled soon for tenant ${tenantName}")
|
||||
.text("Usage: ${currentValue} out of ${limit} ${unitLabel}s")
|
||||
.icon("warning").color("#F9D916")
|
||||
.icon("warning").color(YELLOW_COLOR)
|
||||
.rule(DefaultRule.builder()
|
||||
.name("API feature warning (sysadmin)")
|
||||
.triggerConfig(ApiUsageLimitNotificationRuleTriggerConfig.builder()
|
||||
@ -123,7 +126,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.API_USAGE_LIMIT)
|
||||
.subject("${feature} feature was disabled for tenant ${tenantName}")
|
||||
.text("Used ${currentValue} out of ${limit} ${unitLabel}s")
|
||||
.icon("block").color("#e91a1a")
|
||||
.icon("block").color(RED_COLOR)
|
||||
.rule(DefaultRule.builder()
|
||||
.name("API feature disabled (sysadmin)")
|
||||
.triggerConfig(ApiUsageLimitNotificationRuleTriggerConfig.builder()
|
||||
@ -147,7 +150,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.RATE_LIMITS)
|
||||
.subject("Rate limits exceeded")
|
||||
.text("Rate limits for ${api} exceeded")
|
||||
.icon("block").color("#e91a1a")
|
||||
.icon("block").color(RED_COLOR)
|
||||
.rule(DefaultRule.builder()
|
||||
.name("Per-tenant rate limits exceeded")
|
||||
.triggerConfig(RateLimitsNotificationRuleTriggerConfig.builder()
|
||||
@ -164,7 +167,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.RATE_LIMITS)
|
||||
.subject("Rate limits exceeded")
|
||||
.text("Rate limits for ${api} exceeded for '${limitLevelEntityName}'")
|
||||
.icon("block").color("#e91a1a")
|
||||
.icon("block").color(RED_COLOR)
|
||||
.rule(DefaultRule.builder()
|
||||
.name("Per-entity rate limits exceeded")
|
||||
.triggerConfig(RateLimitsNotificationRuleTriggerConfig.builder()
|
||||
@ -328,7 +331,7 @@ public class DefaultNotifications {
|
||||
.type(NotificationType.GENERAL)
|
||||
.subject("WARNING: security issue")
|
||||
.text("The platform is configured to use default JWT Signing Key. Please change it on the security settings page")
|
||||
.icon("warning").color("#F9D916")
|
||||
.icon("warning").color(YELLOW_COLOR)
|
||||
.button("Go to settings").link("/security-settings/general")
|
||||
.build();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user