Migrated environment aware to property annotation mechanism, documented properties.
This commit is contained in:
@@ -14,16 +14,28 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Bean which holds the necessary properties for configuring the AMQP
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||
public class AmqpProperties {
|
||||
|
||||
/**
|
||||
* Queue for receiving DMF messages from update server.
|
||||
*/
|
||||
private String receiverConnectorQueueFromSp;
|
||||
|
||||
/**
|
||||
* Exchange for sending DMF messages to update server.
|
||||
*/
|
||||
private String senderForSpExchange;
|
||||
|
||||
/**
|
||||
* Simulator dead letter queue.
|
||||
*/
|
||||
private String deadLetterQueue;
|
||||
|
||||
/**
|
||||
* Simulator dead letter exchange.
|
||||
*/
|
||||
private String deadLetterExchange;
|
||||
|
||||
public String getReceiverConnectorQueueFromSp() {
|
||||
|
||||
@@ -18,8 +18,19 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "hawkbit")
|
||||
public class ClientConfigurationProperties {
|
||||
|
||||
/**
|
||||
* Update server URI.
|
||||
*/
|
||||
private String url = "localhost:8080";
|
||||
|
||||
/**
|
||||
* Update server user name.
|
||||
*/
|
||||
private String username = "admin";
|
||||
|
||||
/**
|
||||
* Update server password.
|
||||
*/
|
||||
private String password = "admin"; // NOSONAR this password is only used for
|
||||
// examples
|
||||
|
||||
|
||||
@@ -13,17 +13,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
/**
|
||||
* Properties for the async configurer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.threadpool")
|
||||
public class AsyncConfigurerThreadpoolProperties {
|
||||
|
||||
/**
|
||||
* Max queue size for central event executor.
|
||||
*/
|
||||
private Integer queuesize = 250;
|
||||
|
||||
/**
|
||||
* Core processing threads for central event executor.
|
||||
*/
|
||||
private Integer corethreads = 5;
|
||||
|
||||
/**
|
||||
* Maximum thread pool size for central event executor.
|
||||
*/
|
||||
private Integer maxthreads = 50;
|
||||
|
||||
/**
|
||||
* When the number of threads is greater than the core, this is the maximum
|
||||
* time that excess idle threads will wait for new tasks before terminating.
|
||||
*/
|
||||
private Long idletimeout = 10000L;
|
||||
|
||||
public Integer getQueuesize() {
|
||||
|
||||
@@ -26,10 +26,9 @@ import org.springframework.security.concurrent.DelegatingSecurityContextExecutor
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
* Central event processors inside update server.
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AsyncConfigurerThreadpoolProperties.class)
|
||||
public class ExecutorAutoConfiguration {
|
||||
@@ -40,7 +39,7 @@ public class ExecutorAutoConfiguration {
|
||||
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
|
||||
|
||||
/**
|
||||
* @return ExecutorService for general pupose multi threaded operations
|
||||
* @return ExecutorService for general purpose multi threaded operations
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
@@ -53,7 +53,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
@EnableConfigurationProperties(DdiSecurityProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
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.HttpControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
@@ -43,17 +44,14 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
@@ -94,17 +92,11 @@ import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSucc
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableWebMvcSecurity
|
||||
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||
public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public class SecurityManagedConfiguration {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
|
||||
|
||||
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 SecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for the internal SP controller API.
|
||||
@@ -123,7 +115,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
private DdiSecurityProperties securityConfiguration;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
@@ -204,13 +196,9 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public FilterRegistrationBean dosFilter() {
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
|
||||
filterRegBean
|
||||
.setFilter(
|
||||
new DosFilter(environment.getProperty("security.dos.filter.maxRead", Integer.class, 200),
|
||||
environment.getProperty("security.dos.filter.maxWrite", Integer.class, 50),
|
||||
environment.getProperty("security.dos.filter.whitelist"), environment
|
||||
.getProperty("security.clients.blacklist"),
|
||||
environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
|
||||
filterRegBean.setFilter(new DosFilter(securityProperties.getDos().getFilter().getMaxRead(),
|
||||
securityProperties.getDos().getFilter().getMaxWrite(), securityProperties.getDos().getWhitelist(),
|
||||
securityProperties.getClients().getBlacklist(), securityProperties.getClients().getRemoteIpHeader()));
|
||||
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
|
||||
return filterRegBean;
|
||||
}
|
||||
@@ -310,8 +298,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
@Configuration
|
||||
@Order(400)
|
||||
@EnableVaadinSecurity
|
||||
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
|
||||
implements EnvironmentAware {
|
||||
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String XFRAME_OPTION_DENY = "DENY";
|
||||
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
|
||||
@@ -320,13 +307,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
private VaadinSecurityContext vaadinSecurityContext;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
}
|
||||
@Autowired
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* post construct for setting the authentication success handler for the
|
||||
@@ -379,13 +361,13 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
// configuration xframe-option
|
||||
final String confXframeOption = environment.getProperty("security.xframe.option", XFRAME_OPTION_DENY);
|
||||
final String confAllowFromUri = environment.getProperty("security.xframe.option.allowfrom");
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri == null) {
|
||||
final String confXframeOption = securityProperties.getXframe().getOption();
|
||||
final String confAllowFromUri = securityProperties.getXframe().getAllowfrom();
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri.isEmpty()) {
|
||||
// if allow-from option is specified but no allowFromUri throw
|
||||
// exception
|
||||
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
|
||||
+ " but no hawkbit.server.security.xframe.option.allowfrom has been set, "
|
||||
+ " but no hawkbit.server.security.xframe.allowfrom has been set, "
|
||||
+ "please ensure to set allow from URIs");
|
||||
}
|
||||
|
||||
@@ -461,7 +443,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public static class IdRestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
private DdiSecurityProperties securityConfiguration;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
|
||||
@@ -11,6 +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.api.HostnameResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
|
||||
@@ -1,30 +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.url;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the server e.g. the server's URL which must be configured.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server")
|
||||
public class ServerProperties {
|
||||
|
||||
private String url = "http://localhost:8080";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,6 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
|
||||
* The spring Redis configuration which is enabled by using the profile
|
||||
* {@code redis} to use a Redis server as cache.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RedisProperties.class)
|
||||
|
||||
@@ -14,14 +14,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Bean which holds the necessary properties for configuring the Redis
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server.redis")
|
||||
public class RedisProperties {
|
||||
|
||||
/**
|
||||
* Redis server hostname.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Redis server port.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "hawkbit.controller")
|
||||
public class ControllerPollProperties {
|
||||
|
||||
/**
|
||||
* Recommended target polling time for DDI API. Final choice is up to the
|
||||
* target.
|
||||
*/
|
||||
private String pollingTime = "00:05:00";
|
||||
|
||||
/**
|
||||
* Assumed time frame where the target is considered overdue when no DDI
|
||||
* polling has been registered by the update server.
|
||||
*/
|
||||
private String pollingOverdueTime = "00:05:00";
|
||||
|
||||
public String getPollingTime() {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Properties for the server e.g. the server's URL which must be configured.
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server")
|
||||
public class ServerProperties {
|
||||
/**
|
||||
* Defines under which URI the update server can be reached. Used to
|
||||
* calculate download URLs for DMF transmitted update actions.
|
||||
*/
|
||||
private String url = "http://localhost:8080";
|
||||
|
||||
private final Build build = new Build();
|
||||
|
||||
public Build getBuild() {
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build information of the hawkBit instance. Influeneced by maven.
|
||||
*
|
||||
*/
|
||||
public static class Build {
|
||||
/**
|
||||
* Project artifact ID.
|
||||
*/
|
||||
private String artifact = "";
|
||||
|
||||
/**
|
||||
* Project name.
|
||||
*/
|
||||
private String name = "";
|
||||
|
||||
/**
|
||||
* Project description.
|
||||
*/
|
||||
private String description = "";
|
||||
|
||||
/**
|
||||
* Project version.
|
||||
*/
|
||||
private String version = "";
|
||||
|
||||
public String getArtifact() {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setArtifact(final String artifact) {
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setVersion(final String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTok
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
|
||||
import org.eclipse.hawkbit.security.PreAuthenficationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -55,7 +55,7 @@ public class AmqpControllerAuthentfication {
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties secruityProperties;
|
||||
private DdiSecurityProperties secruityProperties;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -137,7 +137,7 @@ public class AmqpControllerAuthentfication {
|
||||
this.controllerManagement = controllerManagement;
|
||||
}
|
||||
|
||||
public void setSecruityProperties(final SecurityProperties secruityProperties) {
|
||||
public void setSecruityProperties(final DdiSecurityProperties secruityProperties) {
|
||||
this.secruityProperties = secruityProperties;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Bean which holds the necessary properties for configuring the AMQP
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
|
||||
public class AmqpProperties {
|
||||
|
||||
/**
|
||||
* DMF API dead letter queue.
|
||||
*/
|
||||
private String deadLetterQueue = "dmf_connector_deadletter";
|
||||
|
||||
/**
|
||||
* DMF API dead letter exchange.
|
||||
*/
|
||||
private String deadLetterExchange = "dmf.connector.deadletter";
|
||||
|
||||
/**
|
||||
* DMF API receiving queue.
|
||||
*/
|
||||
private String receiverQueue = "dmf_receiver";
|
||||
|
||||
/**
|
||||
* Missing queue fatal, see
|
||||
* {@link SimpleMessageListenerContainer#setMissingQueuesFatal(boolean)}.
|
||||
*/
|
||||
private boolean missingQueuesFatal = false;
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ 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.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -68,7 +68,7 @@ public class AmqpControllerAuthentficationTest {
|
||||
|
||||
authenticationManager = new AmqpControllerAuthentfication();
|
||||
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
|
||||
final SecurityProperties secruityProperties = mock(SecurityProperties.class);
|
||||
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
|
||||
when(secruityProperties.getRpSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||
authenticationManager.setSecruityProperties(secruityProperties);
|
||||
systemManagement = mock(SystemManagement.class);
|
||||
|
||||
@@ -40,10 +40,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
|
||||
/**
|
||||
* General configuration for the SP Repository.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@EnableJpaRepositories(basePackages = { "org.eclipse.hawkbit.repository" })
|
||||
@EnableTransactionManagement
|
||||
|
||||
@@ -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.SecurityProperties;
|
||||
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 SecurityProperties 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.
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -18,7 +18,7 @@ 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.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
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 {
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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 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.
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server.ddi.security")
|
||||
public class DdiSecurityProperties {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.server.ddi.security.rp")
|
||||
public static class RpProperties {
|
||||
|
||||
/**
|
||||
* HTTP header field for common name of a DDI target client certificate.
|
||||
*/
|
||||
private String cnHeader = "X-Ssl-Client-Cn";
|
||||
|
||||
/**
|
||||
* HTTP header field for issuer hash of a DDI target client certificate.
|
||||
*/
|
||||
private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d";
|
||||
|
||||
/**
|
||||
* List of trusted (reverse proxy) IP addresses for performing DDI
|
||||
* client certificate authentication.
|
||||
*/
|
||||
private List<String> trustedIPs;
|
||||
|
||||
/**
|
||||
* @return the cnHeader
|
||||
*/
|
||||
public String getCnHeader() {
|
||||
return cnHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cnHeader
|
||||
* the cnHeader to set
|
||||
*/
|
||||
public void setCnHeader(final String cnHeader) {
|
||||
this.cnHeader = cnHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sslIssuerHashHeader
|
||||
*/
|
||||
public String getSslIssuerHashHeader() {
|
||||
return sslIssuerHashHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sslIssuerHashHeader
|
||||
* the sslIssuerHashHeader to set
|
||||
*/
|
||||
public void setSslIssuerHashHeader(final String sslIssuerHashHeader) {
|
||||
this.sslIssuerHashHeader = sslIssuerHashHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the trustedIPs
|
||||
*/
|
||||
public List<String> getTrustedIPs() {
|
||||
return trustedIPs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trustedIPs
|
||||
* the trustedIPs to set
|
||||
*/
|
||||
public void setTrustedIPs(final List<String> trustedIPs) {
|
||||
this.trustedIPs = trustedIPs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for anonymous enable configuration.
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.server.ddi.security.authentication.anonymous")
|
||||
public static class AnoymousAuthenticationProperties {
|
||||
|
||||
/**
|
||||
* Set to true to enable anonymous DDI client authentication.
|
||||
*/
|
||||
private Boolean enabled = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* @param enabled
|
||||
* the enabled to set
|
||||
*/
|
||||
public void setEnabled(final Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabled
|
||||
*/
|
||||
public Boolean getEnabled() {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,130 +1,181 @@
|
||||
/**
|
||||
* 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 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 security.
|
||||
*
|
||||
*
|
||||
* Security related hawkbit configuration.
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties
|
||||
@ConfigurationProperties("hawkbit.server.security")
|
||||
public class SecurityProperties {
|
||||
|
||||
private final Clients clients = new Clients();
|
||||
|
||||
private final Dos dos = new Dos();
|
||||
private final Xframe xframe = new Xframe();
|
||||
|
||||
public Dos getDos() {
|
||||
return dos;
|
||||
}
|
||||
|
||||
public Clients getClients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
public Xframe getXframe() {
|
||||
return xframe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for reverse proxy configuration.
|
||||
* Defines the XFrameOption policy.
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.server.controller.security.rp")
|
||||
public static class RpProperties {
|
||||
private String cnHeader = "X-Ssl-Client-Cn";
|
||||
private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d";
|
||||
private List<String> trustedIPs;
|
||||
public static class Xframe {
|
||||
|
||||
/**
|
||||
* @return the cnHeader
|
||||
* XFrame option. Allowed values: SAMEORIGIN, DENY, ALLOW-FROM
|
||||
*/
|
||||
public String getCnHeader() {
|
||||
return cnHeader;
|
||||
private String option = "DENY";
|
||||
|
||||
/**
|
||||
* ALLOW-FROM defined URL, has to be filled in case ALLOW-FROM option is
|
||||
* selected.
|
||||
*/
|
||||
private String allowfrom = "";
|
||||
|
||||
public String getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cnHeader
|
||||
* the cnHeader to set
|
||||
*/
|
||||
public void setCnHeader(final String cnHeader) {
|
||||
this.cnHeader = cnHeader;
|
||||
public void setOption(final String option) {
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sslIssuerHashHeader
|
||||
*/
|
||||
public String getSslIssuerHashHeader() {
|
||||
return sslIssuerHashHeader;
|
||||
public String getAllowfrom() {
|
||||
return allowfrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sslIssuerHashHeader
|
||||
* the sslIssuerHashHeader to set
|
||||
*/
|
||||
public void setSslIssuerHashHeader(final String sslIssuerHashHeader) {
|
||||
this.sslIssuerHashHeader = sslIssuerHashHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the trustedIPs
|
||||
*/
|
||||
public List<String> getTrustedIPs() {
|
||||
return trustedIPs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trustedIPs
|
||||
* the trustedIPs to set
|
||||
*/
|
||||
public void setTrustedIPs(final List<String> trustedIPs) {
|
||||
this.trustedIPs = trustedIPs;
|
||||
public void setAllowfrom(final String allowfrom) {
|
||||
this.allowfrom = allowfrom;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class for anonymous enable configuration.
|
||||
* Security configuration related to clients.
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.server.controller.security.authentication.anonymous")
|
||||
public static class AnoymousAuthenticationProperties {
|
||||
private Boolean enabled = Boolean.FALSE;
|
||||
public static class Clients {
|
||||
|
||||
/**
|
||||
* @param enabled
|
||||
* the enabled to set
|
||||
* Blacklisted client (IP addresses) for for DDI and Management API.
|
||||
*/
|
||||
public void setEnabled(final Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
private String blacklist = "";
|
||||
|
||||
/**
|
||||
* @return the enabled
|
||||
* Name of the http header from which the remote ip is extracted.
|
||||
*/
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
private String remoteIpHeader = "X-Forwarded-For";
|
||||
|
||||
public String getBlacklist() {
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
public void setBlacklist(final String blacklist) {
|
||||
this.blacklist = blacklist;
|
||||
}
|
||||
|
||||
public String getRemoteIpHeader() {
|
||||
return remoteIpHeader;
|
||||
}
|
||||
|
||||
public void setRemoteIpHeader(final String remoteIpHeader) {
|
||||
this.remoteIpHeader = remoteIpHeader;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RpProperties rppProperties;
|
||||
/**
|
||||
* Denial of service protection related properties.
|
||||
*
|
||||
*/
|
||||
public static class Dos {
|
||||
|
||||
@Autowired
|
||||
private AnoymousAuthenticationProperties authenticationsProperties;
|
||||
/**
|
||||
* 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}";
|
||||
|
||||
public String getRpCnHeader() {
|
||||
return rppProperties.getCnHeader();
|
||||
/**
|
||||
* Maximum number of status updates that the controller can report for
|
||||
* an action (0 to disable).
|
||||
*/
|
||||
private int maxStatusEntriesPerAction = 1000;
|
||||
|
||||
/**
|
||||
* Maximum number of attributes that the controller can report;
|
||||
*/
|
||||
private int maxAttributeEntriesPerTarget = 100;
|
||||
|
||||
private final Filter filter = new Filter();
|
||||
|
||||
public Filter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public String getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
public void setWhitelist(final String whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
}
|
||||
|
||||
public int getMaxStatusEntriesPerAction() {
|
||||
return maxStatusEntriesPerAction;
|
||||
}
|
||||
|
||||
public void setMaxStatusEntriesPerAction(final int maxStatusEntriesPerAction) {
|
||||
this.maxStatusEntriesPerAction = maxStatusEntriesPerAction;
|
||||
}
|
||||
|
||||
public int getMaxAttributeEntriesPerTarget() {
|
||||
return maxAttributeEntriesPerTarget;
|
||||
}
|
||||
|
||||
public void setMaxAttributeEntriesPerTarget(final int maxAttributeEntriesPerTarget) {
|
||||
this.maxAttributeEntriesPerTarget = maxAttributeEntriesPerTarget;
|
||||
}
|
||||
|
||||
public static class Filter {
|
||||
|
||||
/**
|
||||
* # Maximum number of allowed REST read/GET requests per second per
|
||||
* client.
|
||||
*/
|
||||
int maxRead = 200;
|
||||
|
||||
/**
|
||||
* Maximum number of allowed REST write/(PUT/POST/etc.) requests per
|
||||
* second per client.
|
||||
*/
|
||||
int maxWrite = 50;
|
||||
|
||||
public int getMaxRead() {
|
||||
return maxRead;
|
||||
}
|
||||
|
||||
public void setMaxRead(final int maxRead) {
|
||||
this.maxRead = maxRead;
|
||||
}
|
||||
|
||||
public int getMaxWrite() {
|
||||
return maxWrite;
|
||||
}
|
||||
|
||||
public void setMaxWrite(final int maxWrite) {
|
||||
this.maxWrite = maxWrite;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getRpSslIssuerHashHeader() {
|
||||
return rppProperties.getSslIssuerHashHeader();
|
||||
}
|
||||
|
||||
public List<String> getRpTrustedIPs() {
|
||||
return rppProperties.getTrustedIPs();
|
||||
}
|
||||
|
||||
public Boolean getAnonymousEnabled() {
|
||||
return authenticationsProperties.getEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,90 +11,24 @@ package org.eclipse.hawkbit.util;
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Bean which contains all informations about the SP software, e.g. like
|
||||
* version, built time etc. from the environment.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class SPInfo implements EnvironmentAware {
|
||||
public class SPInfo {
|
||||
|
||||
// package private for testing purposes
|
||||
static final String UNKNOWN_VERSION = "unknown";
|
||||
|
||||
static final String UNKNOWN_CREDENTIAL = "unknown credential";
|
||||
|
||||
private Environment environmentData;
|
||||
|
||||
@Autowired
|
||||
private MultipartConfigElement configElement;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
|
||||
* springframework.core.env. Environment)
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environmentData = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version in string format, e.g. 1.0.0 or {@code "UNKNOWN"} in
|
||||
* case the SP version info cannot be determined.
|
||||
*/
|
||||
public String getVersion() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("info.build.version", UNKNOWN_VERSION);
|
||||
}
|
||||
return UNKNOWN_VERSION;
|
||||
}
|
||||
|
||||
public String getSupportEmail() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("hawkbit.server.email.support");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getRequestAccountEmail() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("hawkbit.server.email.request.account");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getDemoTenant() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("hawkbit.server.demo.tenant");
|
||||
}
|
||||
return UNKNOWN_CREDENTIAL;
|
||||
}
|
||||
|
||||
public String getDemoUser() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("hawkbit.server.demo.user");
|
||||
}
|
||||
return UNKNOWN_CREDENTIAL;
|
||||
|
||||
}
|
||||
|
||||
public String getDemoPassword() {
|
||||
if (environmentData != null) {
|
||||
return environmentData.getProperty("hawkbit.server.demo.password");
|
||||
}
|
||||
return UNKNOWN_CREDENTIAL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max file size to upload artifact files in bytes which has
|
||||
* been configured.
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
package org.eclipse.hawkbit.ui;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for Management UI customization.
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server.ui")
|
||||
public class UiProperties {
|
||||
|
||||
private final Links links = new Links();
|
||||
private final Login login = new Login();
|
||||
private final Demo demo = new Demo();
|
||||
|
||||
public Login getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public Links getLinks() {
|
||||
return links;
|
||||
}
|
||||
|
||||
public Demo getDemo() {
|
||||
return demo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demo account login information.
|
||||
*
|
||||
*/
|
||||
public static class Demo {
|
||||
|
||||
/**
|
||||
* Demo tenant.
|
||||
*/
|
||||
private String tenant = "DEFAULT";
|
||||
/**
|
||||
* Demo user name.
|
||||
*/
|
||||
private String user = "admin";
|
||||
|
||||
/**
|
||||
* Demo user password.
|
||||
*/
|
||||
private String password = "admin";
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
public void setTenant(final String tenant) {
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(final String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Links to potentially other systems (e.g. support, user management etc.).
|
||||
*
|
||||
*/
|
||||
public static class Links {
|
||||
/**
|
||||
* Link to product support.
|
||||
*/
|
||||
private String support = "";
|
||||
|
||||
/**
|
||||
* Link to request a system account, access.
|
||||
*/
|
||||
private String requestAccount = "";
|
||||
|
||||
/**
|
||||
* Link to user management.
|
||||
*/
|
||||
private String userManagement = "";
|
||||
|
||||
public String getSupport() {
|
||||
return support;
|
||||
}
|
||||
|
||||
public void setSupport(final String support) {
|
||||
this.support = support;
|
||||
}
|
||||
|
||||
public String getRequestAccount() {
|
||||
return requestAccount;
|
||||
}
|
||||
|
||||
public void setRequestAccount(final String requestAccount) {
|
||||
this.requestAccount = requestAccount;
|
||||
}
|
||||
|
||||
public String getUserManagement() {
|
||||
return userManagement;
|
||||
}
|
||||
|
||||
public void setUserManagement(final String userManagement) {
|
||||
this.userManagement = userManagement;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration of login view.
|
||||
*
|
||||
*/
|
||||
public static class Login {
|
||||
|
||||
private final Cookie cookie = new Cookie();
|
||||
|
||||
public Cookie getCookie() {
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cookie configuration for login credential cookie.
|
||||
*
|
||||
*/
|
||||
public static class Cookie {
|
||||
/**
|
||||
* Secure cookie enabled.
|
||||
*/
|
||||
private boolean secure = true;
|
||||
|
||||
public boolean isSecure() {
|
||||
return secure;
|
||||
}
|
||||
|
||||
public void setSecure(final boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,16 +15,14 @@ import javax.servlet.http.Cookie;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
|
||||
import org.eclipse.hawkbit.ui.UiProperties;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||
import org.eclipse.hawkbit.util.SPInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -61,7 +59,7 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
*/
|
||||
@SpringView(name = "")
|
||||
@UIScope
|
||||
public class LoginView extends VerticalLayout implements View, EnvironmentAware {
|
||||
public class LoginView extends VerticalLayout implements View {
|
||||
private static final String LOGIN_TEXTFIELD = "login-textfield";
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class);
|
||||
@@ -76,7 +74,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
private I18N i18n;
|
||||
|
||||
@Autowired
|
||||
private transient SPInfo spInfo;
|
||||
private transient UiProperties uiProperties;
|
||||
|
||||
@Autowired
|
||||
private transient MultitenancyIndicator multiTenancyIndicator;
|
||||
@@ -86,9 +84,6 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
private PasswordField password;
|
||||
private Button signin;
|
||||
|
||||
private Boolean secureCookie = Boolean.TRUE;
|
||||
private String userManagementLoginUrl;
|
||||
|
||||
void loginAuthenticationFailedNotification() {
|
||||
final Notification notification = new Notification(i18n.get("notification.login.failed.title"));
|
||||
notification.setDescription(i18n.get("notification.login.failed.description"));
|
||||
@@ -119,7 +114,8 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
final URI spURI = Page.getCurrent().getLocation();
|
||||
final String lookForDemoFragment = spURI.toString();
|
||||
if (lookForDemoFragment.contains("?demo")) {
|
||||
login(spInfo.getDemoTenant(), spInfo.getDemoUser(), spInfo.getDemoPassword(), false);
|
||||
login(uiProperties.getDemo().getTenant(), uiProperties.getDemo().getUser(),
|
||||
uiProperties.getDemo().getPassword(), false);
|
||||
}
|
||||
|
||||
final Component loginForm = buildLoginForm();
|
||||
@@ -243,18 +239,18 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
links.addComponent(demoLink);
|
||||
demoLink.addStyleName(ValoTheme.LINK_SMALL);
|
||||
|
||||
if (spInfo.getRequestAccountEmail() != null) {
|
||||
if (!uiProperties.getLinks().getRequestAccount().isEmpty()) {
|
||||
final Link requestAccountLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_REQUESTACCOUNT,
|
||||
i18n.get("link.requestaccount.name"), spInfo.getRequestAccountEmail(), FontAwesome.SHOPPING_CART,
|
||||
"", linkStyle, true);
|
||||
i18n.get("link.requestaccount.name"), uiProperties.getLinks().getRequestAccount(),
|
||||
FontAwesome.SHOPPING_CART, "", linkStyle, true);
|
||||
links.addComponent(requestAccountLink);
|
||||
requestAccountLink.addStyleName(ValoTheme.LINK_SMALL);
|
||||
}
|
||||
|
||||
if (userManagementLoginUrl != null) {
|
||||
if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
|
||||
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
|
||||
i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
|
||||
linkStyle, true);
|
||||
i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
|
||||
FontAwesome.USERS, "_blank", linkStyle, true);
|
||||
links.addComponent(userManagementLink);
|
||||
userManagementLink.addStyleName(ValoTheme.LINK_SMALL);
|
||||
}
|
||||
@@ -315,7 +311,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
// 100 days
|
||||
tenantCookie.setMaxAge(3600 * 24 * 100);
|
||||
tenantCookie.setHttpOnly(true);
|
||||
tenantCookie.setSecure(secureCookie);
|
||||
tenantCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
|
||||
VaadinService.getCurrentResponse().addCookie(tenantCookie);
|
||||
}
|
||||
|
||||
@@ -324,7 +320,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
// 100 days
|
||||
usernameCookie.setMaxAge(3600 * 24 * 100);
|
||||
usernameCookie.setHttpOnly(true);
|
||||
usernameCookie.setSecure(secureCookie);
|
||||
usernameCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
|
||||
VaadinService.getCurrentResponse().addCookie(usernameCookie);
|
||||
}
|
||||
|
||||
@@ -368,16 +364,4 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
|
||||
loginAuthenticationFailedNotification();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
|
||||
* springframework.core.env. Environment)
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
secureCookie = environment.getProperty("hawkbit.server.ui.login.cookie.secure", Boolean.class, Boolean.TRUE);
|
||||
userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,16 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.ServerProperties;
|
||||
import org.eclipse.hawkbit.im.authentication.PermissionService;
|
||||
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
|
||||
import org.eclipse.hawkbit.ui.UiProperties;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
|
||||
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||
import org.eclipse.hawkbit.util.SPInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
@@ -42,7 +41,6 @@ import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.UIScope;
|
||||
import com.vaadin.ui.Alignment;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.Button.ClickEvent;
|
||||
import com.vaadin.ui.Button.ClickListener;
|
||||
import com.vaadin.ui.Component;
|
||||
import com.vaadin.ui.CustomComponent;
|
||||
@@ -50,7 +48,6 @@ import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.Link;
|
||||
import com.vaadin.ui.MenuBar;
|
||||
import com.vaadin.ui.MenuBar.Command;
|
||||
import com.vaadin.ui.MenuBar.MenuItem;
|
||||
import com.vaadin.ui.VerticalLayout;
|
||||
import com.vaadin.ui.themes.ValoTheme;
|
||||
@@ -61,11 +58,17 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
*/
|
||||
@SpringComponent
|
||||
@UIScope
|
||||
public final class DashboardMenu extends CustomComponent implements EnvironmentAware {
|
||||
public final class DashboardMenu extends CustomComponent {
|
||||
|
||||
@Autowired
|
||||
private I18N i18n;
|
||||
|
||||
@Autowired
|
||||
private transient UiProperties uiProperties;
|
||||
|
||||
@Autowired
|
||||
private transient ServerProperties serverProperties;
|
||||
|
||||
private static final long serialVersionUID = 5394474618559481462L;
|
||||
|
||||
public static final String ID = "dashboard-menu";
|
||||
@@ -81,8 +84,8 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
@Autowired
|
||||
private transient PermissionService permissionService;
|
||||
|
||||
@Autowired
|
||||
private transient SPInfo spInfo;
|
||||
// @Autowired
|
||||
// private transient SPInfo spInfo;
|
||||
|
||||
@Autowired
|
||||
private final List<DashboardMenuItem> dashboardVaadinViews = new ArrayList<>();
|
||||
@@ -91,8 +94,6 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
|
||||
private boolean accessibleViewsEmpty;
|
||||
|
||||
private String userManagementLoginUrl;
|
||||
|
||||
/**
|
||||
* initializing the view and creating the layout, cannot be done in the
|
||||
* custructor because the constructor will be called by spring and the
|
||||
@@ -162,20 +163,20 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
links.addComponent(docuLink);
|
||||
links.setComponentAlignment(docuLink, Alignment.BOTTOM_CENTER);
|
||||
|
||||
if (userManagementLoginUrl != null) {
|
||||
if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
|
||||
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
|
||||
i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
|
||||
linkStyle, true);
|
||||
i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
|
||||
FontAwesome.USERS, "_blank", linkStyle, true);
|
||||
userManagementLink.setDescription(i18n.get("link.usermanagement.name"));
|
||||
links.addComponent(userManagementLink);
|
||||
userManagementLink.setSizeFull();
|
||||
links.setComponentAlignment(userManagementLink, Alignment.BOTTOM_CENTER);
|
||||
}
|
||||
|
||||
if (spInfo.getSupportEmail() != null) {
|
||||
if (!uiProperties.getLinks().getSupport().isEmpty()) {
|
||||
final Link supportLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_SUPPORT,
|
||||
i18n.get("link.support.name"), spInfo.getSupportEmail(), FontAwesome.ENVELOPE_O, "", linkStyle,
|
||||
true);
|
||||
i18n.get("link.support.name"), uiProperties.getLinks().getSupport(), FontAwesome.ENVELOPE_O, "",
|
||||
linkStyle, true);
|
||||
supportLink.setDescription(i18n.get("link.support.name"));
|
||||
supportLink.setSizeFull();
|
||||
links.addComponent(supportLink);
|
||||
@@ -222,12 +223,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
settingsItem.setDescription(user.getUsername());
|
||||
}
|
||||
|
||||
settingsItem.addItem("Sign Out", new Command() {
|
||||
@Override
|
||||
public void menuSelected(final MenuItem selectedItem) {
|
||||
Page.getCurrent().setLocation("/UI/logout");
|
||||
}
|
||||
});
|
||||
settingsItem.addItem("Sign Out", selectedItem -> Page.getCurrent().setLocation("/UI/logout"));
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -254,14 +250,11 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
}
|
||||
|
||||
private Component buildToggleButton() {
|
||||
final Button valoMenuToggleButton = new Button("Menu", new ClickListener() {
|
||||
@Override
|
||||
public void buttonClick(final ClickEvent event) {
|
||||
if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
|
||||
getCompositionRoot().removeStyleName(STYLE_VISIBLE);
|
||||
} else {
|
||||
getCompositionRoot().addStyleName(STYLE_VISIBLE);
|
||||
}
|
||||
final Button valoMenuToggleButton = new Button("Menu", (ClickListener) event -> {
|
||||
if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
|
||||
getCompositionRoot().removeStyleName(STYLE_VISIBLE);
|
||||
} else {
|
||||
getCompositionRoot().addStyleName(STYLE_VISIBLE);
|
||||
}
|
||||
});
|
||||
valoMenuToggleButton.setIcon(FontAwesome.LIST);
|
||||
@@ -307,7 +300,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
final Label label = new Label();
|
||||
label.setSizeFull();
|
||||
label.setStyleName("version-layout");
|
||||
label.setValue(spInfo.getVersion());
|
||||
label.setValue(serverProperties.getBuild().getVersion());
|
||||
return label;
|
||||
}
|
||||
|
||||
@@ -341,11 +334,6 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
menuButtons.forEach(button -> button.postViewChange(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dashboard view type by a given view name.
|
||||
*
|
||||
@@ -411,12 +399,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
|
||||
setDescription(view.getDashboardCaptionLong());
|
||||
/* Avoid double click */
|
||||
setDisableOnClick(true);
|
||||
addClickListener(new ClickListener() {
|
||||
@Override
|
||||
public void buttonClick(final ClickEvent event) {
|
||||
event.getComponent().getUI().getNavigator().navigateTo(view.getViewName());
|
||||
}
|
||||
});
|
||||
addClickListener(event -> event.getComponent().getUI().getNavigator().navigateTo(view.getViewName()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user