Completed migration to ConfigurationProperties annotation. Added boot metadata generation to build.

This commit is contained in:
Kai Zimmermann
2016-02-25 17:59:46 +01:00
parent 0b8e693cec
commit ab18e12b69
39 changed files with 348 additions and 200 deletions

3
.gitignore vendored
View File

@@ -16,13 +16,12 @@
*.jar
*.war
######################
# Sonar
######################
.sonar_lock
# Eclipse IDE
.factorypath
*.pydevproject
.project
.metadata

9
MIGRATION.md Normal file
View File

@@ -0,0 +1,9 @@
# hawkBit Migration Guides
## Release 0.2
### Configuration Property changes
- hawkbit.server.controller._ have changed to hawkbit.server.ddi._
- info.build._ have changed to hawkbit.server.build._
- hawkbit.server.demo._ have changed to hawkbit.server.ui.demo._
- hawkbit.server.email.support has changed to hawkbit.server.ui.links.support
- hawkbit.server.email.request.account has changed to hawkbit.server.ui.links.requestAccount
- hawkbit.server.im.login.url has changed to hawkbit.server.ui.links.userManagement

View File

@@ -100,7 +100,6 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
@@ -116,6 +115,11 @@
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>

View File

@@ -9,12 +9,14 @@
package org.eclipse.hawkbit.simulator.amqp;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Bean which holds the necessary properties for configuring the AMQP
* connection.
*
*/
@Component
@ConfigurationProperties("hawkbit.device.simulator.amqp")
public class AmqpProperties {

View File

@@ -7,23 +7,20 @@
# http://www.eclipse.org/legal/epl-v10.html
#
# need to re-name these properties in the defaulthawkbit.properties and code!
hawkbit.server.controller.security.authentication.anonymous.enabled=true
hawkbit.server.controller.security.authentication.header.enabled=false
hawkbit.server.controller.security.authentication.targettoken.enabled=false
hawkbit.server.controller.security.authentication.gatewaytoken.enabled=false
hawkbit.server.ddi.security.authentication.anonymous.enabled=true
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
spring.profiles.active=amqp
vaadin.servlet.productionMode=false
vaadin.static.servlet.productionMode=false
## Configuration for RabbitMQ integration
hawkbit.server.amqp.username=guest
hawkbit.server.amqp.password=guest
hawkbit.server.amqp.virtualHost=/
hawkbit.server.amqp.host=localhost
hawkbit.server.amqp.port=5672
hawkbit.server.amqp.deadLetterQueue=sp_deadletter
hawkbit.server.amqp.deadLetterExchange=sp.deadletter
hawkbit.server.amqp.receiverQueue=sp_receiver
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtualHost=/
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver

View File

@@ -87,5 +87,10 @@
<artifactId>google-collections</artifactId>
<version>1.0-rc2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -9,12 +9,14 @@
package org.eclipse.hawkbit.mgmt.client;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Configuration bean which holds the configuration of the client e.g. the base
* URL of the hawkbit-server and the credentials to use the RESTful Management
* API.
*/
@Component
@ConfigurationProperties(prefix = "hawkbit")
public class ClientConfigurationProperties {

View File

@@ -11,4 +11,4 @@ hawkbit.url=localhost:8080
hawkbit.username=admin
hawkbit.password=admin
spring.main.banner-mode=OFF
spring.main.show-banner=false

View File

@@ -72,5 +72,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -1,27 +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.autoconfigure.conf;
import org.eclipse.hawkbit.ControllerPollProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* Enable the Controlle Poll.
*
*
*
*/
@Configuration
@ConditionalOnClass(ControllerPollProperties.class)
@EnableConfigurationProperties(ControllerPollProperties.class)
public class ControllerPollAutoConfiguration {
}

View File

@@ -9,11 +9,13 @@
package org.eclipse.hawkbit.autoconfigure.scheduling;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Properties for the async configurer.
*
*/
@Component
@ConfigurationProperties("hawkbit.threadpool")
public class AsyncConfigurerThreadpoolProperties {

View File

@@ -33,12 +33,12 @@ import org.eclipse.hawkbit.rest.resource.RestConstants;
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.DosFilter;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
import org.eclipse.hawkbit.security.HttpDownloadAuthenticationFilter;
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,7 +96,7 @@ public class SecurityManagedConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
@Autowired
private SecurityProperties securityProperties;
private HawkbitSecurityProperties securityProperties;
/**
* {@link WebSecurityConfigurer} for the internal SP controller API.
@@ -124,7 +124,7 @@ public class SecurityManagedConfiguration {
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
securityConfiguration.getRpCnHeader(), securityConfiguration.getRpSslIssuerHashHeader(),
securityConfiguration.getRp().getCnHeader(), securityConfiguration.getRp().getSslIssuerHashHeader(),
systemManagement, tenantAware);
securityHeaderFilter.setAuthenticationManager(authenticationManager());
securityHeaderFilter.setCheckForPrincipalChanges(true);
@@ -150,7 +150,7 @@ public class SecurityManagedConfiguration {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
}
if (securityConfiguration.getAnonymousEnabled()) {
if (securityConfiguration.getAuthentication().getAnonymous().isEnabled()) {
LOG.info(
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
@@ -181,7 +181,7 @@ public class SecurityManagedConfiguration {
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRp().getTrustedIPs()));
}
}
@@ -197,8 +197,9 @@ public class SecurityManagedConfiguration {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
filterRegBean.setFilter(new DosFilter(securityProperties.getDos().getFilter().getMaxRead(),
securityProperties.getDos().getFilter().getMaxWrite(), securityProperties.getDos().getWhitelist(),
securityProperties.getClients().getBlacklist(), securityProperties.getClients().getRemoteIpHeader()));
securityProperties.getDos().getFilter().getMaxWrite(),
securityProperties.getDos().getFilter().getWhitelist(), securityProperties.getClients().getBlacklist(),
securityProperties.getClients().getRemoteIpHeader()));
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
return filterRegBean;
}
@@ -308,7 +309,7 @@ public class SecurityManagedConfiguration {
@Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
@Autowired
private SecurityProperties securityProperties;
private HawkbitSecurityProperties securityProperties;
/**
* post construct for setting the authentication success handler for the
@@ -466,7 +467,7 @@ public class SecurityManagedConfiguration {
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRp().getTrustedIPs()));
}
}

View File

@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.autoconfigure.url;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.hawkbit.ServerProperties;
import org.eclipse.hawkbit.HawkbitServerProperties;
import org.eclipse.hawkbit.api.HostnameResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -28,11 +28,11 @@ import com.google.common.base.Throwables;
*
*/
@Configuration
@EnableConfigurationProperties(ServerProperties.class)
@EnableConfigurationProperties(HawkbitServerProperties.class)
public class PropertyHostnameResolverAutoConfiguration {
@Autowired
private ServerProperties serverProperties;
private HawkbitServerProperties serverProperties;
/**
* @return the default autoconfigure hostname resolver implementation which

View File

@@ -37,6 +37,11 @@
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->

View File

@@ -9,12 +9,14 @@
package org.eclipse.hawkbit.cache;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Bean which holds the necessary properties for configuring the Redis
* connection.
*
*/
@Component
@ConfigurationProperties("hawkbit.server.redis")
public class RedisProperties {

View File

@@ -43,6 +43,11 @@
<artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -9,14 +9,13 @@
package org.eclipse.hawkbit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Defines the polling time for the controllers in HH:MM:SS notation.
*
*
*
*/
@Component
@ConfigurationProperties(prefix = "hawkbit.controller")
public class ControllerPollProperties {

View File

@@ -9,13 +9,15 @@
package org.eclipse.hawkbit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Properties for the server e.g. the server's URL which must be configured.
*
*/
@Component
@ConfigurationProperties("hawkbit.server")
public class ServerProperties {
public class HawkbitServerProperties {
/**
* Defines under which URI the update server can be reached. Used to
* calculate download URLs for DMF transmitted update actions.

View File

@@ -22,35 +22,35 @@ public enum TenantConfigurationKey {
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_HEADER_ENABLED("authentication.header.enabled",
"hawkbit.server.controller.security.authentication.header.enabled", Boolean.FALSE.toString()),
"hawkbit.server.ddi.security.authentication.header.enabled", Boolean.FALSE.toString()),
/**
*
*/
AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME("authentication.header.authority",
"hawkbit.server.controller.security.authentication.header.authority", Boolean.FALSE.toString()),
"hawkbit.server.ddi.security.authentication.header.authority", Boolean.FALSE.toString()),
/**
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED("authentication.targettoken.enabled",
"hawkbit.server.controller.security.authentication.targettoken.enabled", Boolean.FALSE.toString()),
"hawkbit.server.ddi.security.authentication.targettoken.enabled", Boolean.FALSE.toString()),
/**
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED("authentication.gatewaytoken.enabled",
"hawkbit.server.controller.security.authentication.gatewaytoken.enabled", Boolean.FALSE.toString()),
"hawkbit.server.ddi.security.authentication.gatewaytoken.enabled", Boolean.FALSE.toString()),
/**
* string value which holds the name of the security token key.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME("authentication.gatewaytoken.name",
"hawkbit.server.controller.security.authentication.gatewaytoken.name", null),
"hawkbit.server.ddi.security.authentication.gatewaytoken.name", null),
/**
* string value which holds the actual security-key of the gateway security
* token.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY("authentication.gatewaytoken.key",
"hawkbit.server.controller.security.authentication.gatewaytoken.key", null);
"hawkbit.server.ddi.security.authentication.gatewaytoken.key", null);
private final String keyName;
private final String defaultKeyName;

View File

@@ -60,6 +60,11 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->

View File

@@ -21,9 +21,9 @@ import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
import org.eclipse.hawkbit.security.PreAuthenficationFilter;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,8 +78,8 @@ public class AmqpControllerAuthentfication {
filterChain.add(gatewaySecurityTokenFilter);
final ControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new ControllerPreAuthenticatedSecurityHeaderFilter(
secruityProperties.getRpCnHeader(), secruityProperties.getRpSslIssuerHashHeader(), systemManagement,
tenantAware);
secruityProperties.getRp().getCnHeader(), secruityProperties.getRp().getSslIssuerHashHeader(),
systemManagement, tenantAware);
filterChain.add(securityHeaderFilter);
final ControllerPreAuthenticateSecurityTokenFilter securityTokenFilter = new ControllerPreAuthenticateSecurityTokenFilter(

View File

@@ -10,12 +10,14 @@ package org.eclipse.hawkbit.amqp;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Bean which holds the necessary properties for configuring the AMQP
* connection.
*
*/
@Component
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
public class AmqpProperties {

View File

@@ -23,8 +23,9 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.junit.Before;
import org.junit.Test;
@@ -68,8 +69,11 @@ public class AmqpControllerAuthentficationTest {
authenticationManager = new AmqpControllerAuthentfication();
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
when(secruityProperties.getRpSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
final Rp rp = mock(Rp.class);
when(secruityProperties.getRp()).thenReturn(rp);
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
authenticationManager.setSecruityProperties(secruityProperties);
systemManagement = mock(SystemManagement.class);
authenticationManager.setSystemManagement(systemManagement);

View File

@@ -99,6 +99,11 @@
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>

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

@@ -33,7 +33,7 @@ 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.SecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -84,7 +84,7 @@ public class ControllerManagement {
private ActionStatusRepository actionStatusRepository;
@Autowired
private SecurityProperties securityProperties;
private HawkbitSecurityProperties securityProperties;
/**
* Refreshes the time of the last time the controller has been connected to

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

@@ -18,12 +18,10 @@ 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.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.AdviceMode;
@@ -47,7 +45,8 @@ import com.mongodb.MongoClientOptions;
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
@EnableConfigurationProperties({ DdiSecurityProperties.class, ControllerPollProperties.class })
// @EnableConfigurationProperties({ DdiSecurityProperties.class,
// ControllerPollProperties.class })
@Profile("test")
public class TestConfiguration implements AsyncConfigurer {

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

View File

@@ -25,13 +25,11 @@ import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.util.IpUtil;
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.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
@@ -55,7 +53,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping(ControllerConstants.ARTIFACTS_V1_REQUEST_MAPPING)
public class ArtifactStoreController implements EnvironmentAware {
public class ArtifactStoreController {
private static final Logger LOG = LoggerFactory.getLogger(ArtifactStoreController.class);
@Autowired
@@ -67,14 +65,8 @@ public class ArtifactStoreController implements EnvironmentAware {
@Autowired
private CacheWriteNotify cacheWriteNotify;
private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
private RelaxedPropertyResolver environment;
@Override
public void setEnvironment(final Environment environment) {
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
}
@Autowired
private HawkbitSecurityProperties securityProperties;
/**
* Handles GET {@link Artifact} download request. This could be full or
@@ -138,8 +130,8 @@ public class ArtifactStoreController implements EnvironmentAware {
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
final LocalArtifact artifact) {
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(
request, environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = controllerManagement
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), artifact.getSoftwareModule());

View File

@@ -41,15 +41,13 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.util.IpUtil;
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.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -74,7 +72,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping(ControllerConstants.BASE_V1_REQUEST_MAPPING)
public class RootController implements EnvironmentAware {
public class RootController {
private static final Logger LOG = LoggerFactory.getLogger(RootController.class);
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
@@ -99,16 +97,8 @@ public class RootController implements EnvironmentAware {
@Autowired
private TenantAware tenantAware;
private String requestHeader;
@Override
public void setEnvironment(final Environment environment) {
final RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(environment,
SP_SERVER_CONFIG_PREFIX);
requestHeader = relaxedPropertyResolver.getProperty("security.rp.remote_ip_header", String.class,
"X-Forwarded-For");
}
@Autowired
private HawkbitSecurityProperties securityProperties;
/**
* Returns all artifacts of a given software module and target.
@@ -155,12 +145,13 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerBase({})", targetid);
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (target.getTargetInfo().getUpdateStatus() == TargetUpdateStatus.UNKNOWN) {
LOG.debug("target with {} extsisted but was in status UNKNOWN -> REGISTERED)", targetid);
controllerManagement.updateTargetStatus(target.getTargetInfo(), TargetUpdateStatus.REGISTERED,
System.currentTimeMillis(), IpUtil.getClientIpFromRequest(request, requestHeader));
System.currentTimeMillis(),
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
}
return new ResponseEntity<>(
@@ -195,7 +186,7 @@ public class RootController implements EnvironmentAware {
ResponseEntity<Void> result;
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
if (checkModule(fileName, module)) {
@@ -265,7 +256,8 @@ public class RootController implements EnvironmentAware {
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable final String targetid,
@PathVariable final Long softwareModuleId, @PathVariable final String fileName,
final HttpServletResponse response, final HttpServletRequest request) {
controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
@@ -311,7 +303,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerBasedeploymentAction({},{})", targetid, resource);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -362,7 +354,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", targetid, actionId, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
@@ -469,7 +461,8 @@ public class RootController implements EnvironmentAware {
+ ControllerConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final ConfigData configData,
@PathVariable final String targetid, final HttpServletRequest request) {
controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
controllerManagement.updateControllerAttributes(targetid, configData.getData());
@@ -495,7 +488,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerCancelAction({})", targetid);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -542,7 +535,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("provideCancelActionFeedback for target [{}]: {}", targetid, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, requestHeader));
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(

View File

@@ -24,7 +24,7 @@ hawkbit.server.database=H2
hawkbit.server.database.env=TEST
spring.main.show_banner=false
hawkbit.server.controller.security.authentication.header=true
hawkbit.server.ddi.security.authentication.header=true
hawkbit.server.artifact.repo.upload.maxFileSize=5MB

View File

@@ -59,6 +59,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>

View File

@@ -10,25 +10,34 @@ package org.eclipse.hawkbit.security;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* The common properties for DDI security.
*/
@Component
@ConfigurationProperties("hawkbit.server.ddi.security")
public class DdiSecurityProperties {
private final Rp rp = new Rp();
private final Authentication authentication = new Authentication();
public Authentication getAuthentication() {
return authentication;
}
public Rp getRp() {
return rp;
}
/**
* Inner class for reverse proxy configuration. Defines the security
* properties for authenticating controllers behind a reverse proxy which
* terminates the SSL session at the reverse proxy but adding request header
* which contains the CN of the certificate.
* Reverse proxy configuration. Defines the security properties for
* authenticating controllers behind a reverse proxy which terminates the
* SSL session at the reverse proxy but adding request header which contains
* the CN of the certificate.
*/
@Component
@ConfigurationProperties("hawkbit.server.ddi.security.rp")
public static class RpProperties {
public static class Rp {
/**
* HTTP header field for common name of a DDI target client certificate.
@@ -94,54 +103,119 @@ public class DdiSecurityProperties {
}
/**
* Inner class for anonymous enable configuration.
* DDI Authentication options.
*/
@Component
@ConfigurationProperties("hawkbit.server.ddi.security.authentication.anonymous")
public static class AnoymousAuthenticationProperties {
public static class Authentication {
private final Anonymous anonymous = new Anonymous();
private final Targettoken targettoken = new Targettoken();
private final Gatewaytoken gatewaytoken = new Gatewaytoken();
public Anonymous getAnonymous() {
return anonymous;
}
public Gatewaytoken getGatewaytoken() {
return gatewaytoken;
}
public Targettoken getTargettoken() {
return targettoken;
}
/**
* Target token authentication. Tokens are defined per target.
*
*/
public static class Targettoken {
/**
* Set to true to enable target token authentication.
*/
private boolean enabled = false;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
}
/**
* Gateway token authentication. Tokens are defined per tenant. Use with
* care!
*
*/
public static class Gatewaytoken {
/**
* Gateway token based authentication enabled.
*/
private boolean enabled = false;
/**
* Default gateway token name.
*/
private String name = "";
/**
* Default gateway token itself.
*/
private String key = "";
public boolean isEnabled() {
return enabled;
}
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
}
/**
* Anonymous authentication.
*/
public static class Anonymous {
/**
* Set to true to enable anonymous DDI client authentication.
*/
private Boolean enabled = Boolean.FALSE;
private boolean enabled = false;
/**
* @param enabled
* the enabled to set
*/
public void setEnabled(final Boolean enabled) {
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
/**
* @return the enabled
*/
public Boolean getEnabled() {
public boolean isEnabled() {
return enabled;
}
}
@Autowired
private RpProperties rppProperties;
@Autowired
private AnoymousAuthenticationProperties authenticationsProperties;
public String getRpCnHeader() {
return rppProperties.getCnHeader();
}
public String getRpSslIssuerHashHeader() {
return rppProperties.getSslIssuerHashHeader();
}
public List<String> getRpTrustedIPs() {
return rppProperties.getTrustedIPs();
}
public Boolean getAnonymousEnabled() {
return authenticationsProperties.getEnabled();
}
}

View File

@@ -1,16 +1,25 @@
/**
* 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.security;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Security related hawkbit configuration.
*
*/
@Component
@ConfigurationProperties("hawkbit.server.security")
public class SecurityProperties {
public class HawkbitSecurityProperties {
private final Clients clients = new Clients();
private final Dos dos = new Dos();
private final Xframe xframe = new Xframe();
@@ -100,11 +109,6 @@ public class SecurityProperties {
*/
public static class Dos {
/**
* White list of peer IP addresses for DOS filter (regular expression).
*/
private String whitelist = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|169\\.254\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}";
/**
* Maximum number of status updates that the controller can report for
* an action (0 to disable).
@@ -122,14 +126,6 @@ public class SecurityProperties {
return filter;
}
public String getWhitelist() {
return whitelist;
}
public void setWhitelist(final String whitelist) {
this.whitelist = whitelist;
}
public int getMaxStatusEntriesPerAction() {
return maxStatusEntriesPerAction;
}
@@ -148,6 +144,12 @@ public class SecurityProperties {
public static class Filter {
/**
* White list of peer IP addresses for DOS filter (regular
* expression).
*/
private String whitelist = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|169\\.254\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}";
/**
* # Maximum number of allowed REST read/GET requests per second per
* client.
@@ -160,6 +162,14 @@ public class SecurityProperties {
*/
int maxWrite = 50;
public String getWhitelist() {
return whitelist;
}
public void setWhitelist(final String whitelist) {
this.whitelist = whitelist;
}
public int getMaxRead() {
return maxRead;
}

View File

@@ -213,7 +213,6 @@
<groupId>org.vaadin.addons</groupId>
<artifactId>tokenfield</artifactId>
</dependency>
<!-- To be mentioned in release notes -->
<dependency>
<groupId>org.vaadin.alump.distributionbar</groupId>
<artifactId>dbar-addon</artifactId>
@@ -222,7 +221,11 @@
<groupId>org.vaadin.addons</groupId>
<artifactId>contextmenu</artifactId>
</dependency>
<!-- To be mentioned in release notes -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>

View File

@@ -1,11 +1,21 @@
/**
* 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.ui;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Properties for Management UI customization.
*
*/
@Component
@ConfigurationProperties("hawkbit.server.ui")
public class UiProperties {

View File

@@ -18,7 +18,7 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.ServerProperties;
import org.eclipse.hawkbit.HawkbitServerProperties;
import org.eclipse.hawkbit.im.authentication.PermissionService;
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
import org.eclipse.hawkbit.ui.UiProperties;
@@ -67,7 +67,7 @@ public final class DashboardMenu extends CustomComponent {
private transient UiProperties uiProperties;
@Autowired
private transient ServerProperties serverProperties;
private transient HawkbitServerProperties serverProperties;
private static final long serialVersionUID = 5394474618559481462L;

View File

@@ -559,7 +559,6 @@
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${json.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>