From 352bfcff24f268a382ac6c81f455ee17f89659bc Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Thu, 8 Jun 2017 06:34:47 +0200 Subject: [PATCH] New repository quota on messages per ActionStatus (#531) * New quotaexception for repository quota hit on DDI. Added actionstatus messages quota. Signed-off-by: kaizimmerm * Remove special log handling on the quota exception. Signed-off-by: kaizimmerm * Raise time for slow machines. Signed-off-by: kaizimmerm * Update allure to get rid of log spam in unit tests. Signed-off-by: kaizimmerm * Typos fixed. Signed-off-by: kaizimmerm --- .../hawkbit/exception/SpServerError.java | 7 +-- .../hawkbit/ddi/json/model/DdiStatus.java | 2 - .../rest/resource/DdiDeploymentBaseTest.java | 31 ++++++++- .../amqp/DelayedRequeueExceptionStrategy.java | 5 +- .../repository/ControllerManagement.java | 25 ++++---- .../hawkbit/repository/QuotaManagement.java | 7 +++ .../exception/QuotaExceededException.java | 63 +++++++++++++++++++ .../ToManyAttributeEntriesException.java | 46 -------------- .../TooManyStatusEntriesException.java | 50 --------------- .../repository/PropertiesQuotaManagement.java | 5 ++ .../jpa/JpaControllerManagement.java | 37 ++++++----- .../exception/ResponseExceptionHandler.java | 3 +- .../hawkbit/rest/util/JsonBuilder.java | 12 ++-- .../security/HawkbitSecurityProperties.java | 13 ++++ pom.xml | 2 +- 15 files changed, 162 insertions(+), 146 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TooManyStatusEntriesException.java diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java index dbcf0a1bb..84e5243f2 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java @@ -103,12 +103,7 @@ public enum SpServerError { /** * */ - SP_ACTION_STATUS_TO_MANY_ENTRIES("hawkbit.server.error.action.status.tooManyEntries", "Too many status entries have been inserted."), - - /** - * - */ - SP_ATTRIBUTES_TO_MANY_ENTRIES("hawkbit.server.error.target.attributes.tooManyEntries", "Too many attribute entries have been inserted."), + SP_QUOTA_EXCEEDED("hawkbit.server.error.quota.tooManyEntries", "Too many entries have been inserted."), /** * error message, which describes that the action can not be canceled cause diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java index 64d360b9d..78deeefe8 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java @@ -13,7 +13,6 @@ import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,7 +31,6 @@ public class DdiStatus { @Valid private final DdiResult result; - @Size(min = 0, max = 50) private final List details; /** diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index 0e706c761..13b76aabb 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -232,7 +232,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSetAssignmentResult result = deploymentManagement.assignDistributionSet(ds.getId(), - ActionType.TIMEFORCED, System.currentTimeMillis() + 1_000, Arrays.asList(target.getControllerId())); + ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000, Arrays.asList(target.getControllerId())); final Action action = deploymentManagement .findActiveActionsByTarget(PAGE, result.getAssignedEntity().get(0).getControllerId()).getContent() @@ -255,7 +255,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { + "/controller/v1/4712/deploymentBase/" + action.getId()); // After the time is over we should see a new etag - TimeUnit.MILLISECONDS.sleep(1_000); + TimeUnit.MILLISECONDS.sleep(2_000); mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) @@ -539,7 +539,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { @Test @Description("The server protects itself against to many feedback upload attempts. The test verfies that " + "it is not possible to exceed the configured maximum number of feedback uplods.") - public void toMuchDeplomentActionFeedback() throws Exception { + public void tooMuchDeplomentActionFeedback() throws Exception { final Target target = testdataFactory.createTarget("4712"); final DistributionSet ds = testdataFactory.createDistributionSet(""); @@ -562,6 +562,31 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(status().isForbidden()); } + @Test + @Description("The server protects itself against too large feedback bodies. The test verifies that " + + "it is not possible to exceed the configured maximum number of feedback details.") + public void tooMuchDeploymentActionMessagesInFeedback() throws Exception { + final Target target = testdataFactory.createTarget("4712"); + final DistributionSet ds = testdataFactory.createDistributionSet(""); + + assignDistributionSet(ds.getId(), "4712"); + final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() + .get(0); + + final List messages = new ArrayList<>(); + for (int i = 0; i < 51; i++) { + messages.add(String.valueOf(i)); + } + + final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding", "none", + messages); + mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback", + tenantAware.getCurrentTenant()).content(feedback).contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()); + + } + @Test @Description("Multiple uploads of deployment status feedback to the server.") public void multipleDeplomentActionFeedback() throws Exception { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java index c0276ea12..f86bfbaf3 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java @@ -15,9 +15,8 @@ import javax.validation.ConstraintViolationException; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; +import org.eclipse.hawkbit.repository.exception.QuotaExceededException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException; -import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; -import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler; @@ -72,7 +71,7 @@ public class DelayedRequeueExceptionStrategy extends ConditionalRejectingErrorHa } private boolean quotaHit(final Throwable cause) { - return cause instanceof TooManyStatusEntriesException || cause instanceof ToManyAttributeEntriesException; + return cause instanceof QuotaExceededException; } private boolean doesNotExist(final Throwable cause) { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index 7c29b4e19..a0be62de3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -20,8 +20,7 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; -import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException; +import org.eclipse.hawkbit.repository.exception.QuotaExceededException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -52,9 +51,9 @@ public interface ControllerManagement { * @throws EntityAlreadyExistsException * if a given entity already exists * - * @throws TooManyStatusEntriesException - * if more than the allowed number of status entries are - * inserted + * @throws QuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * @throws EntityNotFoundException * if given action does not exist * @@ -87,9 +86,9 @@ public interface ControllerManagement { * * @return created {@link ActionStatus} entity * - * @throws TooManyStatusEntriesException - * if more than the allowed number of status entries are - * inserted + * @throws QuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * @throws EntityNotFoundException * if given action does not exist */ @@ -106,9 +105,9 @@ public interface ControllerManagement { * * @throws EntityAlreadyExistsException * if a given entity already exists - * @throws TooManyStatusEntriesException - * if more than the allowed number of status entries are - * inserted + * @throws QuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * * @throws EntityNotFoundException * if action status not exist @@ -267,8 +266,8 @@ public interface ControllerManagement { * * @throws EntityNotFoundException * if target that has to be updated could not be found - * @throws ToManyAttributeEntriesException - * if maximum + * @throws QuotaExceededException + * if maximum number of attribzes per target is exceeded */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) Target updateControllerAttributes(@NotEmpty String controllerId, @NotNull Map attributes); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/QuotaManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/QuotaManagement.java index 039736d1a..fa5a133c4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/QuotaManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/QuotaManagement.java @@ -36,4 +36,11 @@ public interface QuotaManagement { */ int getMaxRolloutGroupsPerRollout(); + /** + * @return maximum number of + * {@link ControllerManagement#getActionHistoryMessages(Long, int)} + * for an individual {@link ActionStatus}. + */ + int getMaxMessagesPerActionStatus(); + } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java new file mode 100644 index 000000000..80477ca84 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.exception; + +import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.exception.SpServerError; +import org.eclipse.hawkbit.repository.model.BaseEntity; + +/** + * Thrown if too many entries are added to repository. + * + */ +public final class QuotaExceededException extends AbstractServerRtException { + private static final long serialVersionUID = 1L; + + /** + * Creates a new QuotaExceededException with + * {@link SpServerError#SP_QUOTA_EXCEEDED} error. + */ + public QuotaExceededException() { + super(SpServerError.SP_QUOTA_EXCEEDED); + } + + /** + * @param cause + * for the exception + */ + public QuotaExceededException(final Throwable cause) { + super(SpServerError.SP_QUOTA_EXCEEDED, cause); + } + + /** + * @param type + * that hit quota + * @param inserted + * cause for the hit + * @param quota + * that is defined by the repository + */ + public QuotaExceededException(final Class type, final long inserted, final int quota) { + this(type.getSimpleName(), inserted, quota); + } + + /** + * + * @param type + * that hit quota + * @param inserted + * cause for the hit + * @param quota + * that is defined by the repository + */ + public QuotaExceededException(final String type, final long inserted, final int quota) { + super("Request contains too many entries of {" + type + "}. {" + inserted + "} is bejond the permitted {" + + quota + "}.", SpServerError.SP_QUOTA_EXCEEDED); + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java deleted file mode 100644 index 8800ec13c..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.repository.exception; - -import org.eclipse.hawkbit.exception.AbstractServerRtException; -import org.eclipse.hawkbit.exception.SpServerError; - -/** - * Thrown if too many status entries have been inserted. - */ -public final class ToManyAttributeEntriesException extends AbstractServerRtException { - /** - * - */ - private static final long serialVersionUID = 1L; - - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ATTRIBUTES_TO_MANY_ENTRIES} error. - */ - public ToManyAttributeEntriesException() { - super(SpServerError.SP_ATTRIBUTES_TO_MANY_ENTRIES); - } - - /** - * @param cause - * for the exception - */ - public ToManyAttributeEntriesException(final Throwable cause) { - super(SpServerError.SP_ATTRIBUTES_TO_MANY_ENTRIES, cause); - } - - /** - * @param message - * of the error - */ - public ToManyAttributeEntriesException(final String message) { - super(message, SpServerError.SP_ATTRIBUTES_TO_MANY_ENTRIES); - } -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TooManyStatusEntriesException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TooManyStatusEntriesException.java deleted file mode 100644 index a0fe82d98..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TooManyStatusEntriesException.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.repository.exception; - -import org.eclipse.hawkbit.exception.AbstractServerRtException; -import org.eclipse.hawkbit.exception.SpServerError; - -/** - * Thrown if too many status entries have been inserted. - * - * - * - * - */ -public final class TooManyStatusEntriesException extends AbstractServerRtException { - /** - * - */ - private static final long serialVersionUID = 1L; - - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_REST_BODY_NOT_READABLE} error. - */ - public TooManyStatusEntriesException() { - super(SpServerError.SP_ACTION_STATUS_TO_MANY_ENTRIES); - } - - /** - * @param cause - * for the exception - */ - public TooManyStatusEntriesException(final Throwable cause) { - super(SpServerError.SP_ACTION_STATUS_TO_MANY_ENTRIES, cause); - } - - /** - * @param message - * of the error - */ - public TooManyStatusEntriesException(final String message) { - super(message, SpServerError.SP_ACTION_STATUS_TO_MANY_ENTRIES); - } -} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/PropertiesQuotaManagement.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/PropertiesQuotaManagement.java index 480f8dafd..1e0f5e28c 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/PropertiesQuotaManagement.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/PropertiesQuotaManagement.java @@ -43,4 +43,9 @@ public class PropertiesQuotaManagement implements QuotaManagement { return securityProperties.getDos().getMaxRolloutGroupsPerRollout(); } + @Override + public int getMaxMessagesPerActionStatus() { + return securityProperties.getDos().getMaxMessagesPerActionStatus(); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index cd5fedb5e..da42c6e99 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -31,8 +31,7 @@ import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; -import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException; +import org.eclipse.hawkbit.repository.exception.QuotaExceededException; import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; @@ -79,7 +78,6 @@ import org.springframework.validation.annotation.Validated; @Validated public class JpaControllerManagement implements ControllerManagement { private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class); - private static final Logger LOG_DOS = LoggerFactory.getLogger("server-security.dos"); @Autowired private EntityManager entityManager; @@ -277,7 +275,8 @@ public class JpaControllerManagement implements ControllerManagement { break; default: // information status entry - check for a potential DOS attack - checkForToManyStatusEntries(action); + checkForTooManyStatusEntries(action); + checkForTooManyStatusMessages(actionStatus); break; } @@ -287,6 +286,14 @@ public class JpaControllerManagement implements ControllerManagement { return action; } + private void checkForTooManyStatusMessages(final JpaActionStatus actionStatus) { + if (actionStatus.getMessages().size() > quotaManagement.getMaxMessagesPerActionStatus()) { + throw new QuotaExceededException("ActionStatus messages", actionStatus.getMessages().size(), + quotaManagement.getMaxStatusEntriesPerAction()); + } + + } + private void handleFinishedCancelation(final JpaActionStatus actionStatus, final JpaAction action) { // in case of successful cancellation we also report the success at // the canceled action itself. @@ -340,7 +347,8 @@ public class JpaControllerManagement implements ControllerManagement { break; default: // information status entry - check for a potential DOS attack - checkForToManyStatusEntries(action); + checkForTooManyStatusEntries(action); + checkForTooManyStatusMessages(actionStatus); break; } @@ -360,16 +368,14 @@ public class JpaControllerManagement implements ControllerManagement { targetRepository.save(mergedTarget); } - private void checkForToManyStatusEntries(final JpaAction action) { + private void checkForTooManyStatusEntries(final JpaAction action) { if (quotaManagement.getMaxStatusEntriesPerAction() > 0) { final Long statusCount = actionStatusRepository.countByAction(action); if (statusCount >= quotaManagement.getMaxStatusEntriesPerAction()) { - LOG_DOS.error( - "Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!", + throw new QuotaExceededException(ActionStatus.class, statusCount, quotaManagement.getMaxStatusEntriesPerAction()); - throw new TooManyStatusEntriesException(String.valueOf(quotaManagement.getMaxStatusEntriesPerAction())); } } } @@ -406,10 +412,8 @@ public class JpaControllerManagement implements ControllerManagement { target.getControllerAttributes().putAll(data); if (target.getControllerAttributes().size() > quotaManagement.getMaxAttributeEntriesPerTarget()) { - LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!", + throw new QuotaExceededException("Controller attribues", target.getControllerAttributes().size(), quotaManagement.getMaxAttributeEntriesPerTarget()); - throw new ToManyAttributeEntriesException( - String.valueOf(quotaManagement.getMaxAttributeEntriesPerTarget())); } target.setRequestControllerAttributes(false); @@ -488,7 +492,8 @@ public class JpaControllerManagement implements ControllerManagement { final JpaActionStatus statusMessage = create.build(); statusMessage.setAction(action); - checkForToManyStatusEntries(action); + checkForTooManyStatusEntries(action); + checkForTooManyStatusMessages(statusMessage); return actionStatusRepository.save(statusMessage); } @@ -533,11 +538,11 @@ public class JpaControllerManagement implements ControllerManagement { // For negative and large value of messageCount, limit the number of // messages. - int limit = messageCount < 0 || messageCount >= RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT + final int limit = messageCount < 0 || messageCount >= RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT ? RepositoryConstants.MAX_ACTION_HISTORY_MSG_COUNT : messageCount; - PageRequest pageable = new PageRequest(0, limit, new Sort(Direction.DESC, "occurredAt")); - Page messages = actionStatusRepository.findMessagesByActionIdAndMessageNotLike(pageable, actionId, + final PageRequest pageable = new PageRequest(0, limit, new Sort(Direction.DESC, "occurredAt")); + final Page messages = actionStatusRepository.findMessagesByActionIdAndMessageNotLike(pageable, actionId, RepositoryConstants.SERVER_MESSAGE_PREFIX + "%"); LOG.debug("Retrieved {} message(s) from action history for action {}.", messages.getNumberOfElements(), diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java index d34c0631d..c36d2e3a8 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java @@ -56,8 +56,7 @@ public class ResponseExceptionHandler { ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_DELETE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); - ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_STATUS_TO_MANY_ENTRIES, HttpStatus.FORBIDDEN); - ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ATTRIBUTES_TO_MANY_ENTRIES, HttpStatus.FORBIDDEN); + ERROR_TO_HTTP_STATUS.put(SpServerError.SP_QUOTA_EXCEEDED, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_CANCELABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_CREATION_FAILED_MISSING_MODULE, HttpStatus.BAD_REQUEST); diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java index 0a70f5a8a..fe0c23b7f 100644 --- a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java +++ b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.rest.util; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -206,20 +207,23 @@ public abstract class JsonBuilder { * @throws JSONException */ public static String deploymentActionFeedback(final String id, final String execution) throws JSONException { - return deploymentActionFeedback(id, execution, "none", RandomStringUtils.randomAscii(1000)); + return deploymentActionFeedback(id, execution, "none", Arrays.asList(RandomStringUtils.randomAscii(1000))); } public static String deploymentActionFeedback(final String id, final String execution, final String message) throws JSONException { - return deploymentActionFeedback(id, execution, "none", message); + return deploymentActionFeedback(id, execution, "none", Arrays.asList(message)); } public static String deploymentActionFeedback(final String id, final String execution, final String finished, final String message) throws JSONException { - final List messages = new ArrayList<>(); - messages.add(message); + return deploymentActionFeedback(id, execution, finished, Arrays.asList(message)); + } + + public static String deploymentActionFeedback(final String id, final String execution, final String finished, + final Collection messages) throws JSONException { return new JSONObject().put("id", id).put("time", "20140511T121314") .put("status", diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java index 5f78fc9cb..d51435d4b 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java @@ -109,6 +109,11 @@ public class HawkbitSecurityProperties { */ private int maxRolloutGroupsPerRollout = 500; + /** + * Maximum number of messages per ActionStatus + */ + private int maxMessagesPerActionStatus = 50; + private final Filter filter = new Filter(); private final Filter uiFilter = new Filter(); @@ -128,6 +133,14 @@ public class HawkbitSecurityProperties { this.maxStatusEntriesPerAction = maxStatusEntriesPerAction; } + public int getMaxMessagesPerActionStatus() { + return maxMessagesPerActionStatus; + } + + public void setMaxMessagesPerActionStatus(final int maxMessagesPerActionStatus) { + this.maxMessagesPerActionStatus = maxMessagesPerActionStatus; + } + public int getMaxAttributeEntriesPerTarget() { return maxAttributeEntriesPerTarget; } diff --git a/pom.xml b/pom.xml index 19de05b60..732f10eaf 100644 --- a/pom.xml +++ b/pom.xml @@ -155,7 +155,7 @@ 1.1.0.Final - 1.4.22 + 1.5.4 2.6.4 1.6.5 1.1.6