Merge remote-tracking branch 'eclipse/master' into harmonize-test-documentation

This commit is contained in:
Kai Zimmermann
2016-03-04 18:14:26 +01:00
61 changed files with 1216 additions and 652 deletions

View File

@@ -40,10 +40,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
/**
* General configuration for the SP Repository.
*
*
*
*
*
*/
@EnableJpaRepositories(basePackages = { "org.eclipse.hawkbit.repository" })
@EnableTransactionManagement

View File

@@ -0,0 +1,50 @@
/**
* 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;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Rollout Management properties.
*
*/
@Component
@ConfigurationProperties("hawkbit.rollout")
public class RolloutProperties {
private final Scheduler scheduler = new Scheduler();
public Scheduler getScheduler() {
return scheduler;
}
/**
* Rollout scheduler configuration.
*/
public static class Scheduler {
// used by @Scheduled annotation which needs constant
public static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.rollout.scheduler.fixedDelay:30000}";
/**
* Schedule where the rollout scheduler looks necessary state changes in
* milliseconds.
*/
private long fixedDelay = 30000L;
public long getFixedDelay() {
return fixedDelay;
}
public void setFixedDelay(final long fixedDelay) {
this.fixedDelay = fixedDelay;
}
}
}

View File

@@ -21,45 +21,47 @@ import org.springframework.transaction.annotation.Transactional;
/**
* {@link ActionStatus} repository.
*
*
*
*
*/
@Transactional(readOnly = true)
public interface ActionStatusRepository
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> {
/**
* @param target
* Counts {@link ActionStatus} entries of given {@link Action} in
* repository.
*
* @param action
* @return
* to count status entries
* @return number of actions in repository
*/
Long countByAction(Action action);
/**
* Counts {@link ActionStatus} entries of given {@link Action} with given
* {@link Status} in repository.
*
* @param action
* @param retrieved
* @return
* to count status entries
* @param status
* to filter for
* @return number of actions in repository
*/
Long countByActionAndStatus(Action action, Status retrieved);
Long countByActionAndStatus(Action action, Status status);
/**
* Retrieves all {@link ActionStatus} entries from repository of given
* {@link Action}.
*
* @param pageReq
* parameters
* @param action
* @return
* of the status entries
* @return pages list of {@link ActionStatus} entries
*/
Page<ActionStatus> findByAction(Pageable pageReq, Action action);
/**
* @param pageReq
* @param action
* @return
*/
Page<ActionStatus> findByActionOrderByIdDesc(Pageable pageReq, Action action);
/**
* Finds all status updates for the defined action and target order by
* {@link ActionStatus#getId()} desc including
* Finds all status updates for the defined action and target including
* {@link ActionStatus#getMessages()}.
*
* @param pageReq
@@ -71,6 +73,6 @@ public interface ActionStatusRepository
* @return Page with found targets
*/
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
Page<ActionStatus> getByActionOrderByIdDesc(Pageable pageReq, Action action);
Page<ActionStatus> getByAction(Pageable pageReq, Action action);
}

View File

@@ -33,13 +33,11 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -57,7 +55,7 @@ import org.springframework.validation.annotation.Validated;
@Transactional(readOnly = true)
@Validated
@Service
public class ControllerManagement implements EnvironmentAware {
public class ControllerManagement {
private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class);
private static final Logger LOG_DOS = LoggerFactory.getLogger("server-security.dos");
@@ -85,9 +83,8 @@ public class ControllerManagement implements EnvironmentAware {
@Autowired
private ActionStatusRepository actionStatusRepository;
private Integer maxCount = 1000;
private Integer maxAttributes = 100;
@Autowired
private HawkbitSecurityProperties securityProperties;
/**
* Refreshes the time of the last time the controller has been connected to
@@ -379,15 +376,16 @@ public class ControllerManagement implements EnvironmentAware {
}
private void checkForToManyStatusEntries(final Action action) {
if (maxCount > 0) {
if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
final Long statusCount = actionStatusRepository.countByAction(action);
if (statusCount >= maxCount) {
if (statusCount >= securityProperties.getDos().getMaxStatusEntriesPerAction()) {
LOG_DOS.error(
"Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!",
maxCount);
throw new ToManyStatusEntriesException(String.valueOf(maxCount));
securityProperties.getDos().getMaxStatusEntriesPerAction());
throw new ToManyStatusEntriesException(
String.valueOf(securityProperties.getDos().getMaxStatusEntriesPerAction()));
}
}
}
@@ -436,10 +434,12 @@ public class ControllerManagement implements EnvironmentAware {
target.getTargetInfo().getControllerAttributes().putAll(data);
if (target.getTargetInfo().getControllerAttributes().size() > maxAttributes) {
if (target.getTargetInfo().getControllerAttributes().size() > securityProperties.getDos()
.getMaxAttributeEntriesPerTarget()) {
LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
maxAttributes);
throw new ToManyAttributeEntriesException(String.valueOf(maxAttributes));
securityProperties.getDos().getMaxAttributeEntriesPerTarget());
throw new ToManyAttributeEntriesException(
String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
}
target.getTargetInfo().setLastTargetQuery(System.currentTimeMillis());
@@ -447,19 +447,6 @@ public class ControllerManagement implements EnvironmentAware {
return targetRepository.save(target);
}
/*
* (non-Javadoc)
*
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
* springframework.core.env. Environment)
*/
@Override
public void setEnvironment(final Environment environment) {
final RelaxedPropertyResolver env = new RelaxedPropertyResolver(environment, "hawkbit.server.");
maxCount = env.getProperty("security.dos.maxStatusEntriesPerAction", Integer.class, 1000);
maxAttributes = env.getProperty("security.dos.maxAttributeEntriesPerTarget", Integer.class, 100);
}
/**
* Registers retrieved status for given {@link Target} and {@link Action} if
* it does not exist yet.

View File

@@ -925,7 +925,7 @@ public class DeploymentManagement {
/**
* retrieves all the {@link ActionStatus} entries of the given
* {@link Action} and {@link Target} in the order latest first.
* {@link Action} and {@link Target}.
*
* @param pageReq
* pagination parameter
@@ -937,12 +937,12 @@ public class DeploymentManagement {
* @return the corresponding {@link Page} of {@link ActionStatus}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
public Page<ActionStatus> findActionStatusMessagesByActionInDescOrder(final Pageable pageReq, final Action action,
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action,
final boolean withMessages) {
if (withMessages) {
return actionStatusRepository.getByActionOrderByIdDesc(pageReq, action);
return actionStatusRepository.getByAction(pageReq, action);
} else {
return actionStatusRepository.findByActionOrderByIdDesc(pageReq, action);
return actionStatusRepository.findByAction(pageReq, action);
}
}

View File

@@ -46,7 +46,6 @@ import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -55,14 +54,10 @@ import org.springframework.validation.annotation.Validated;
/**
* Service layer for generating SP reportings.
*
*
*
*
*/
@Transactional(readOnly = true)
@Validated
@Service
@ConfigurationProperties
public class ReportManagement {
@Value("${spring.jpa.database}")

View File

@@ -10,14 +10,13 @@ package org.eclipse.hawkbit.repository;
import java.util.List;
import org.eclipse.hawkbit.RolloutProperties;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -31,15 +30,10 @@ import org.springframework.stereotype.Component;
// don't active the rollout scheduler in test, otherwise it is hard to test
// rolloutmanagement and leads weird side-effects maybe.
@Profile("!test")
public class RolloutScheduler implements EnvironmentAware {
public class RolloutScheduler {
private static final Logger logger = LoggerFactory.getLogger(RolloutScheduler.class);
private static final String PROP_SCHEDULER_DELAY = "hawkbit.rollout.scheduler.fixedDelay";
private static final long DEFAULT_SCHEDULER_DELAY = 30000L;
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${" + PROP_SCHEDULER_DELAY + ":"
+ DEFAULT_SCHEDULER_DELAY + "}";
@Autowired
private TenantAware tenantAware;
@@ -52,7 +46,8 @@ public class RolloutScheduler implements EnvironmentAware {
@Autowired
private SystemSecurityContext systemSecurityContext;
private long fixedDelay = DEFAULT_SCHEDULER_DELAY;
@Autowired
private RolloutProperties rolloutProperties;
/**
* Scheduler method called by the spring-async mechanism. Retrieves all
@@ -60,7 +55,7 @@ public class RolloutScheduler implements EnvironmentAware {
* tenant the {@link RolloutManagement#checkRunningRollouts(long)} in the
* {@link SystemSecurityContext}.
*/
@Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
@Scheduled(initialDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER)
public void rolloutScheduler() {
logger.debug("rollout schedule checker has been triggered.");
// run this code in system code privileged to have the necessary
@@ -76,16 +71,11 @@ public class RolloutScheduler implements EnvironmentAware {
logger.info("Checking rollouts for {} tenants", tenants.size());
for (final String tenant : tenants) {
tenantAware.runAsTenant(tenant, () -> {
rolloutManagement.checkRunningRollouts(fixedDelay);
rolloutManagement.checkRunningRollouts(rolloutProperties.getScheduler().getFixedDelay());
return null;
});
}
return null;
});
}
@Override
public void setEnvironment(final Environment environment) {
fixedDelay = environment.getProperty(PROP_SCHEDULER_DELAY, Long.class, DEFAULT_SCHEDULER_DELAY);
}
}

View File

@@ -17,8 +17,8 @@ import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator;
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator.DatabaseCleanupUtil;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
@@ -47,7 +47,7 @@ import com.mongodb.MongoClientOptions;
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
@EnableConfigurationProperties({ SecurityProperties.class, ControllerPollProperties.class })
@EnableConfigurationProperties({ DdiSecurityProperties.class, ControllerPollProperties.class })
@Profile("test")
public class TestConfiguration implements AsyncConfigurer {

View File

@@ -70,8 +70,8 @@ public class ControllerManagementTest extends AbstractIntegrationTest {
.isEqualTo(TargetUpdateStatus.IN_SYNC);
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusMessagesByActionInDescOrder(pageReq, savedAction, false)
.getNumberOfElements()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction, false).getNumberOfElements())
.isEqualTo(3);
}
@Test

View File

@@ -10,7 +10,7 @@
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
spring.data.mongodb.port=28017
hawkbit.server.controller.security.authentication.header.enabled=true
hawkbit.server.ddi.security.authentication.header.enabled=true
hawkbit.server.artifact.repo.upload.maxFileSize=5MB
@@ -29,11 +29,6 @@ flyway.initOnMigrate=true
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
#spring.jpa.show-sql=true
# SP Controller configuration
# DDI configuration
hawkbit.controller.pollingTime=00:01:00
hawkbit.controller.pollingOverdueTime=00:01:00
## Configuration for RabbitMQ integration
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
hawkbit.controller.pollingOverdueTime=00:01:00