From d86c20b3545aeca1a4d14ff7fd210f0b198c055c Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 6 Oct 2022 11:46:24 +0300 Subject: [PATCH 1/2] Additional validation for AuditLog entity --- .../org/thingsboard/server/common/data/audit/AuditLog.java | 3 +++ .../thingsboard/server/dao/audit/AuditLogServiceImpl.java | 6 +++++- .../org/thingsboard/server/dao/service/DataValidator.java | 2 +- .../thingsboard/server/dao/service/NoXssValidatorTest.java | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java index e87a1a6380..f88aabaa64 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java @@ -22,6 +22,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.*; +import org.thingsboard.server.common.data.validation.NoXss; @ApiModel @EqualsAndHashCode(callSuper = true) @@ -34,10 +35,12 @@ public class AuditLog extends BaseData { private CustomerId customerId; @ApiModelProperty(position = 5, value = "JSON object with Entity id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private EntityId entityId; + @NoXss @ApiModelProperty(position = 6, value = "Name of the logged entity", example = "Thermometer", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String entityName; @ApiModelProperty(position = 7, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private UserId userId; + @NoXss @ApiModelProperty(position = 8, value = "Unique user name(email) of the user that performed some action on logged entity", example = "tenant@thingsboard.org", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String userName; @ApiModelProperty(position = 9, value = "String represented Action type", example = "ADDED", accessMode = ApiModelProperty.AccessMode.READ_ONLY) diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index e3ea775b0e..24e7ef4c7f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -382,7 +382,11 @@ public class AuditLogServiceImpl implements AuditLogService { AuditLog auditLogEntry = createAuditLogEntry(tenantId, entityId, entityName, customerId, userId, userName, actionType, actionData, actionStatus, actionFailureDetails); log.trace("Executing logAction [{}]", auditLogEntry); - auditLogValidator.validate(auditLogEntry, AuditLog::getTenantId); + try { + auditLogValidator.validate(auditLogEntry, AuditLog::getTenantId); + } catch (Exception e) { + return Futures.immediateFailedFuture(e); + } List> futures = Lists.newArrayListWithExpectedSize(INSERTS_PER_ENTRY); futures.add(auditLogDao.saveByTenantId(auditLogEntry)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index 28223f3e7f..beb4a7ebc1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -62,7 +62,7 @@ public abstract class DataValidator> { } return old; } catch (DataValidationException e) { - log.error("Data object is invalid: [{}]", e.getMessage()); + log.error("{} object is invalid: [{}]", data == null ? "Data" : data.getClass().getSimpleName(), e.getMessage()); throw e; } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/NoXssValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/NoXssValidatorTest.java index c4ef964883..36eb76edb5 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/NoXssValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/NoXssValidatorTest.java @@ -42,7 +42,7 @@ public class NoXssValidatorTest { "

Link!!!

1221", "

Please log in to proceed

Username:

Password:



", " ", - "123 bebe", + "123 bebe" }) public void testIsNotValid(String stringWithXss) { boolean isValid = validator.isValid(stringWithXss, mock(ConstraintValidatorContext.class)); From caea6aa27b728f5f31687f149869d03546301bbb Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 6 Oct 2022 13:48:06 +0300 Subject: [PATCH 2/2] Save audit log with entity name replaced if it is malformed --- .../thingsboard/server/common/data/audit/AuditLog.java | 1 - .../thingsboard/server/dao/audit/AuditLogServiceImpl.java | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java index f88aabaa64..b921ea4374 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java @@ -40,7 +40,6 @@ public class AuditLog extends BaseData { private String entityName; @ApiModelProperty(position = 7, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private UserId userId; - @NoXss @ApiModelProperty(position = 8, value = "Unique user name(email) of the user that performed some action on logged entity", example = "tenant@thingsboard.org", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String userName; @ApiModelProperty(position = 9, value = "String represented Action type", example = "ADDED", accessMode = ApiModelProperty.AccessMode.READ_ONLY) diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 24e7ef4c7f..da94141768 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -23,13 +23,13 @@ import com.google.common.collect.Lists; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasName; -import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.audit.ActionStatus; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; @@ -385,7 +385,11 @@ public class AuditLogServiceImpl implements AuditLogService { try { auditLogValidator.validate(auditLogEntry, AuditLog::getTenantId); } catch (Exception e) { - return Futures.immediateFailedFuture(e); + if (StringUtils.contains(e.getMessage(), "value is malformed")) { + auditLogEntry.setEntityName("MALFORMED"); + } else { + return Futures.immediateFailedFuture(e); + } } List> futures = Lists.newArrayListWithExpectedSize(INSERTS_PER_ENTRY); futures.add(auditLogDao.saveByTenantId(auditLogEntry));