Initial check in accordance with Parallel IP

This commit is contained in:
Kai Zimmermann
2016-01-21 13:18:55 +01:00
parent c5e4f1139f
commit 7497ab61ed
763 changed files with 114508 additions and 0 deletions

81
hawkbit-autoconfigure/pom.xml Executable file
View File

@@ -0,0 +1,81 @@
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-autoconfigure</artifactId>
<name>hawkBit :: Spring Boot Autoconfigure</name>
<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-core</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-cache-redis</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-dmf-amqp</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-ui</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-http-security</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-security-core</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-rest-resource</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,27 @@
/**
* 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.amqp;
import org.eclipse.hawkbit.amqp.AmqpConfiguration;
import org.eclipse.hawkbit.amqp.annotation.EnableAmqp;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
/**
* The amqp autoconfiguration.
*
*
*
*/
@Configuration
@ConditionalOnClass(value = AmqpConfiguration.class)
@EnableAmqp
public class AmqpAutoConfiguration {
}

View File

@@ -0,0 +1,197 @@
/**
* 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.cache;
import java.util.Collection;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.cache.TenancyCacheManager;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* A configuration for configuring the spring {@link CacheManager} for specific
* multi-tenancy caching. The caches between tenants must not interfere each
* other.
*
* This is done by providing a special {@link TenantCacheResolver} which
* generates a cache name included the current tenant.
*
*
*
*/
@Configuration
@EnableCaching
public class CacheAutoConfiguration extends CachingConfigurerSupport {
@Autowired
private TenantAware tenantAware;
/**
* @return the default cache manager bean if none other cache manager is
* existing.
*/
@Override
@Bean
@ConditionalOnMissingBean
public TenancyCacheManager cacheManager() {
return new TenantAwareCacheManager(new GuavaCacheManager(), tenantAware);
}
/**
* A {@link SimpleCacheResolver} implementation which includes the
* {@link TenantAware#getCurrentTenant()} into the cache name before
* resolving it.
*
*
*
*
*/
public class TenantCacheResolver extends SimpleCacheResolver {
/*
* (non-Javadoc)
*
* @see org.springframework.cache.interceptor.AbstractCacheResolver#
* resolveCaches(org.springframework
* .cache.interceptor.CacheOperationInvocationContext)
*/
@Override
public Collection<Cache> resolveCaches(final CacheOperationInvocationContext<?> context) {
return super.resolveCaches(context).stream().map(cache -> new TenantCacheWrapper(cache))
.collect(Collectors.toList());
}
/*
* (non-Javadoc)
*
* @see org.springframework.cache.interceptor.SimpleCacheResolver#
* getCacheNames(org.springframework
* .cache.interceptor.CacheOperationInvocationContext)
*/
@Override
protected Collection<String> getCacheNames(final CacheOperationInvocationContext<?> context) {
return super.getCacheNames(context).stream()
.map(cacheName -> tenantAware.getCurrentTenant() + "." + cacheName).collect(Collectors.toList());
}
}
/**
* An {@link Cache} wrapper which returns the name of the cache include the
* {@link TenantAware#getCurrentTenant()}.
*
*
*
*
*/
public class TenantCacheWrapper implements Cache {
private final Cache delegate;
/**
* @param delegate
*/
public TenantCacheWrapper(final Cache delegate) {
this.delegate = delegate;
}
/**
* @return
* @see org.springframework.cache.Cache#getName()
*/
@Override
public String getName() {
return tenantAware.getCurrentTenant() + "." + delegate.getName();
}
/**
* @return
* @see org.springframework.cache.Cache#getNativeCache()
*/
@Override
public Object getNativeCache() {
return delegate.getNativeCache();
}
/**
* @param key
* @return
* @see org.springframework.cache.Cache#get(java.lang.Object)
*/
@Override
public ValueWrapper get(final Object key) {
return delegate.get(key);
}
/**
* @param key
* @param type
* @return
* @see org.springframework.cache.Cache#get(java.lang.Object,
* java.lang.Class)
*/
@Override
public <T> T get(final Object key, final Class<T> type) {
return delegate.get(key, type);
}
/**
* @param key
* @param value
* @see org.springframework.cache.Cache#put(java.lang.Object,
* java.lang.Object)
*/
@Override
public void put(final Object key, final Object value) {
delegate.put(key, value);
}
/**
* @param key
* @param value
* @return
* @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object,
* java.lang.Object)
*/
@Override
public ValueWrapper putIfAbsent(final Object key, final Object value) {
return delegate.putIfAbsent(key, value);
}
/**
* @param key
* @see org.springframework.cache.Cache#evict(java.lang.Object)
*/
@Override
public void evict(final Object key) {
delegate.evict(key);
}
/**
*
* @see org.springframework.cache.Cache#clear()
*/
@Override
public void clear() {
delegate.clear();
}
}
}

View File

@@ -0,0 +1,46 @@
/**
* 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.cache;
import org.eclipse.hawkbit.cache.CacheConstants;
import org.eclipse.hawkbit.cache.TenancyCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* A configuration for configuring a cache for the download id's.
*
* This is done by providing a named cache.
*
*
*
*/
@Configuration
public class DownloadIdCacheAutoConfiguration {
@Autowired
private CacheManager cacheManager;
/**
* Bean for the downlod id cache.
*
* @return the cache
*/
@Bean(name = CacheConstants.DOWNLOAD_ID_CACHE)
public Cache downloadIdCache() {
if (cacheManager instanceof TenancyCacheManager) {
return ((TenancyCacheManager) cacheManager).getDirectCache(CacheConstants.DOWNLOAD_ID_CACHE);
}
return cacheManager.getCache(CacheConstants.DOWNLOAD_ID_CACHE);
}
}

View File

@@ -0,0 +1,27 @@
/**
* 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.cache;
import org.eclipse.hawkbit.cache.RedisConfiguration;
import org.eclipse.hawkbit.cache.annotation.EnableRedis;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
/**
* A configuration for configuring the redis configuration.
*
*
*
*/
@Configuration
@ConditionalOnClass(value = RedisConfiguration.class)
@EnableRedis
public class RedisAutoConfiguration {
}

View File

@@ -0,0 +1,27 @@
/**
* 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

@@ -0,0 +1,28 @@
/**
* 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.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* Autoconfiguration which loads the default configuration properties for
* hawkbit.
*
*
*
*/
@Configuration
@PropertySource("classpath:/hawkbitdefaults.properties")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DefaultPropertiesAutoConfiguration {
}

View File

@@ -0,0 +1,57 @@
/**
* 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.eventbus;
import java.util.concurrent.Executor;
import org.eclipse.hawkbit.eventbus.EventBusSubscriberProcessor;
import org.eclipse.hawkbit.eventbus.EventSubscriber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
/**
*
*
*/
@Configuration
public class EventBusAutoConfiguration {
@Autowired
@Qualifier("asyncExecutor")
private Executor executor;
/**
* Server internal eventBus that allows parallel event processing if the
* subscriber is marked as so.
*
* @return eventbus bean
*/
@Bean
@ConditionalOnMissingBean
public EventBus eventBus() {
return new AsyncEventBus(executor);
}
/**
* @return the {@link EventBusSubscriberProcessor} to find classes annotated
* with {@link EventSubscriber}.
*/
@Bean
@ConditionalOnMissingBean
public EventBusSubscriberProcessor eventBusSubscriberProcessor() {
return new EventBusSubscriberProcessor();
}
}

View File

@@ -0,0 +1,46 @@
/**
* 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.scheduling;
import java.util.concurrent.Executor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
/**
*
*
*/
@Configuration
@EnableAsync
@ConditionalOnMissingBean(AsyncConfigurer.class)
public class AsyncConfigurerAutoConfiguration implements AsyncConfigurer {
@Autowired
@Qualifier("asyncExecutor")
private Executor executor;
@Override
public Executor getAsyncExecutor() {
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
}

View File

@@ -0,0 +1,61 @@
/**
* 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.scheduling;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties for the async configurer.
*
*
*/
@ConfigurationProperties("hawkbit.threadpool")
public class AsyncConfigurerThreadpoolProperties {
private Integer queuesize = 250;
private Integer corethreads = 5;
private Integer maxthreads = 50;
private Long idletimeout = 10000L;
public Integer getQueuesize() {
return queuesize;
}
public void setQueuesize(final Integer queuesize) {
this.queuesize = queuesize;
}
public Integer getCorethreads() {
return corethreads;
}
public void setCorethreads(final Integer corethreads) {
this.corethreads = corethreads;
}
public Integer getMaxthreads() {
return maxthreads;
}
public void setMaxthreads(final Integer maxthreads) {
this.maxthreads = maxthreads;
}
public Long getIdletimeout() {
return idletimeout;
}
public void setIdletimeout(final Long idletimeout) {
this.idletimeout = idletimeout;
}
}

View File

@@ -0,0 +1,78 @@
/**
* 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.scheduling;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
*
*
*/
@Configuration
@EnableConfigurationProperties(AsyncConfigurerThreadpoolProperties.class)
public class ExecutorAutoConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorAutoConfiguration.class);
@Autowired
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
/**
* @return ExecutorService for general pupose multi threaded operations
*/
@Bean
@ConditionalOnMissingBean
public Executor asyncExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(
asyncConfigurerProperties.getQueuesize());
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
asyncConfigurerProperties.getCorethreads(), asyncConfigurerProperties.getMaxthreads(),
asyncConfigurerProperties.getIdletimeout(), TimeUnit.MILLISECONDS, blockingQueue,
new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());
threadPoolExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(final Runnable r, final java.util.concurrent.ThreadPoolExecutor executor) {
LOGGER.warn("Reject runnable for centralExecutorService, reached limit of queue size {}", executor
.getQueue().size());
}
});
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
}
/**
* @return the executor for UI background processes.
*/
@Bean(name = "uiExecutor")
@ConditionalOnMissingBean(name = "uiExecutor")
public Executor uiExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(20);
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 10000, TimeUnit.MILLISECONDS,
blockingQueue, new ThreadFactoryBuilder().setNameFormat("ui-executor-pool-%d").build());
threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
}
}

View File

@@ -0,0 +1,28 @@
/**
* 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.security;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
/**
* Annotation to enable the managed security configuration.
*
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SecurityManagedConfiguration.class)
public @interface EnableHawkbitManagedSecurityConfiguration {
}

View File

@@ -0,0 +1,206 @@
/**
* 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.security;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
import org.eclipse.hawkbit.im.authentication.PermissionService;
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.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
/**
* {@link EnableAutoConfiguration Auto-configuration} for security.
*
*
*
*/
@Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class SecurityAutoConfiguration {
/**
* @return the {@link TenantAware} singleton bean which holds the current
* {@link TenantAware} service and make it accessible in beans which
* cannot access the service directly, e.g. JPA entities.
*/
@Bean
@ConditionalOnMissingBean
public TenantAware tenantAware() {
return new SecurityContextTenantAware();
}
/**
* @return permission service to check if current user has the necessary
* permissions.
*/
@Bean
@ConditionalOnMissingBean
public PermissionService permissionService() {
return new PermissionService();
}
/**
* Creates the auditore aware.
*
* @return the spring security auditore aware
*/
@Bean
@ConditionalOnMissingBean
public AuditorAware<String> auditorAware() {
return new SpringSecurityAuditorAware();
}
/**
* Auto-configuration for the in-memory-user-management.
*
*
*
*/
@Configuration
@ConditionalOnMissingBean(value = { UserAuthenticationFilter.class })
public static class InMemoryUserManagementConfiguration extends GlobalAuthenticationConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryUserManagementConfiguration.class);
@Autowired
private AuthenticationConfiguration configuration;
/*
* (non-Javadoc)
*
* @see org.springframework.security.config.annotation.authentication.
* configurers. GlobalAuthenticationConfigurerAdapter
* #configure(org.springframework.security.config.annotation.
* authentication.builders.AuthenticationManagerBuilder)
*/
@Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
final DaoAuthenticationProvider userDaoAuthenticationProvider = new TenantDaoAuthenticationProvider();
userDaoAuthenticationProvider.setUserDetailsService(userDetailsService());
auth.authenticationProvider(userDaoAuthenticationProvider);
}
/**
* @return the user details service to load a user from memory user
* manager.
*/
@Bean
public UserDetailsService userDetailsService() {
final InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(
new ArrayList<>());
inMemoryUserDetailsManager.setAuthenticationManager(null);
inMemoryUserDetailsManager.createUser(new User("admin", "admin", getAllAuthorities()));
return inMemoryUserDetailsManager;
}
/**
* @return the multi-tenancy indicator to disallow multi-tenancy
*/
@Bean
public MultitenancyIndicator multiTenancyIndicator() {
return new MultitenancyIndicator() {
@Override
public boolean isMultiTenancySupported() {
return false;
}
};
}
private Collection<SimpleGrantedAuthority> getAllAuthorities() {
final List<SimpleGrantedAuthority> allPermissions = new ArrayList<>();
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
for (final Field field : declaredFields) {
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
field.setAccessible(true);
try {
final String permissionName = (String) field.get(null);
allPermissions.add(new SimpleGrantedAuthority(permissionName));
} catch (final IllegalAccessException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
return allPermissions;
}
private static class TenantDaoAuthenticationProvider extends DaoAuthenticationProvider {
/*
* (non-Javadoc)
*
* @see org.springframework.security.authentication.dao.
* AbstractUserDetailsAuthenticationProvider
* #createSuccessAuthentication(java.lang.Object,
* org.springframework.security.core.Authentication,
* org.springframework.security.core.userdetails.UserDetails)
*/
@Override
protected Authentication createSuccessAuthentication(final Object principal,
final Authentication authentication, final UserDetails user) {
final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
authentication.getCredentials(), user.getAuthorities());
result.setDetails(new TenantAwareAuthenticationDetails("DEFAULT", false));
return result;
}
}
/**
* @return the {@link UserAuthenticationFilter} to include into the SP
* security configuration.
* @throws Exception
* lazy bean exception maybe if the authentication manager
* cannot be instantiated
*/
@Bean
public UserAuthenticationFilter userAuthenticationFilter() throws Exception {
return new UserAuthenticationFilterBasicAuth(configuration.getAuthenticationManager());
}
private static final class UserAuthenticationFilterBasicAuth extends BasicAuthenticationFilter
implements UserAuthenticationFilter {
private UserAuthenticationFilterBasicAuth(final AuthenticationManager authenticationManager) {
super(authenticationManager);
}
}
}
}

View File

@@ -0,0 +1,563 @@
/**
* 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.security;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import javax.annotation.PostConstruct;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.cache.CacheConstants;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
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.DosFilter;
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;
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.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;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.vaadin.spring.security.VaadinSecurityContext;
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
import org.vaadin.spring.security.web.VaadinDefaultRedirectStrategy;
import org.vaadin.spring.security.web.VaadinRedirectStrategy;
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
/**
* All configurations related to SP authentication and authorization layer.
*
*
*
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
@EnableWebMvcSecurity
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class SecurityManagedConfiguration implements EnvironmentAware {
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);
}
/**
* {@link WebSecurityConfigurer} for the internal SP controller API.
*
*
*
*/
@Configuration
@Order(300)
static class ControllerSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private ControllerManagement controllerManagement;
@Autowired
private SystemManagement systemManagement;
@Autowired
private TenantAware tenantAware;
@Autowired
private SecurityProperties securityConfiguration;
@Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
@Override
protected void configure(final HttpSecurity http) throws Exception {
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
securityConfiguration.getRpCnHeader(), securityConfiguration.getRpSslIssuerHashHeader(),
systemManagement, tenantAware);
securityHeaderFilter.setAuthenticationManager(authenticationManager());
securityHeaderFilter.setCheckForPrincipalChanges(true);
securityHeaderFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
final HttpControllerPreAuthenticateSecurityTokenFilter securityTokenFilter = new HttpControllerPreAuthenticateSecurityTokenFilter(
systemManagement, tenantAware, controllerManagement);
securityTokenFilter.setAuthenticationManager(authenticationManager());
securityTokenFilter.setCheckForPrincipalChanges(true);
securityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
final HttpControllerPreAuthenticatedGatewaySecurityTokenFilter gatewaySecurityTokenFilter = new HttpControllerPreAuthenticatedGatewaySecurityTokenFilter(
systemManagement, tenantAware);
gatewaySecurityTokenFilter.setAuthenticationManager(authenticationManager());
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
HttpSecurity httpSec = http.csrf().disable().headers()
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
.xssProtection().httpStrictTransportSecurity().and();
if (springSecurityProperties.isRequireSsl()) {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
}
if (securityConfiguration.getAnonymousEnabled()) {
LOG.info(
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
"controllerAnonymousFilter", "anonymous", Collections.singletonList(
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
} else {
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
.addFilter(gatewaySecurityTokenFilter).antMatcher("/*/controller/**").anonymous().disable()
.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
.authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(final HttpServletRequest request, final HttpServletResponse response,
final AuthenticationException authException) throws IOException, ServletException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
}
}).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.security.config.annotation.web.configuration.
* WebSecurityConfigurerAdapter
* #configure(org.springframework.security.config.annotation.
* authentication.builders. AuthenticationManagerBuilder)
*/
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
}
}
/**
* Filter to protect the SP server against denial of service attacks.
*
* @return he spring filter registration bean for registering an denial of
* service protection filter in the filter chain
*/
@Bean
@Order(50)
public FilterRegistrationBean dosFilter() {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
filterRegBean
.setFilter(
new DosFilter(environment.getProperty("security.dos.filter.maxRead", Integer.class, 100),
environment.getProperty("security.dos.filter.maxWrite", Integer.class, 10),
environment.getProperty("security.dos.filter.whitelist"), environment
.getProperty("security.clients.blacklist"),
environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
return filterRegBean;
}
/**
* Filter registration bean for spring etag filter.
*
* @return the spring filter registration bean for registering an etag
* filter in the filter chain
*/
@Bean
@Order(100)
public FilterRegistrationBean eTagFilter() {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
// eclude the URLs for downloading artifacts, so no eTag is generated in
// the
// ShallowEtagHeaderFilter, just using the SH1 hash of the artifact
// itself as 'ETag', because
// otherwise the file will be copied in memory!
filterRegBean.setFilter(new ExcludePathAwareShallowETagFilter(
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download", "/{tenant}/controller/artifacts/**",
"/{targetid}/softwaremodules/{softwareModuleId}/artifacts/**"));
return filterRegBean;
}
/**
* Security configuration for the REST management API of the health url.
*
*
*/
@Configuration
@Order(310)
public static class HealthSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.regexMatcher("/system/health").csrf().disable().httpBasic().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
/**
* Security configuration for the REST management API.
*
*
*/
@Configuration
@Order(350)
public static class RestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private UserAuthenticationFilter userAuthenticationFilter;
@Autowired
private SystemManagement systemManagement;
@Autowired
private TenantAware tenantAware;
@Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
@Override
protected void configure(final HttpSecurity http) throws Exception {
HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system.*").csrf().disable();
if (springSecurityProperties.isRequireSsl()) {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
}
httpSec.addFilterBefore(new Filter() {
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
userAuthenticationFilter.init(filterConfig);
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
userAuthenticationFilter.doFilter(request, response, chain);
}
@Override
public void destroy() {
userAuthenticationFilter.destroy();
}
}, RequestHeaderAuthenticationFilter.class)
.addFilterAfter(
new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement),
RequestHeaderAuthenticationFilter.class)
.authorizeRequests().anyRequest().authenticated()
.antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN).antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/**")
.hasAnyAuthority(SpPermission.SYSTEM_DIAG);
}
}
/**
* {@link WebSecurityConfigurer} for external (management) access.
*
*
*/
@Configuration
@Order(400)
@EnableVaadinSecurity
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
implements EnvironmentAware {
private static final String XFRAME_OPTION_DENY = "DENY";
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
private static final String XFAME_OPTION_ALLOW_FROM = "ALLOW-FROM";
@Autowired
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);
}
/**
* post construct for setting the authentication success handler for the
* vaadin security context.
*/
@PostConstruct
public void afterPropertiesSet() {
this.vaadinSecurityContext.addAuthenticationSuccessHandler(redirectSaveHandler());
}
@Bean(name = "authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* @return The VaadinRedirectStategy
*/
@Bean
public VaadinRedirectStrategy vaadinRedirectStrategy() {
return new VaadinDefaultRedirectStrategy();
}
/**
* @return the vaadin success authentication handler
*/
@Bean
public VaadinAuthenticationSuccessHandler redirectSaveHandler() {
final VaadinUrlAuthenticationSuccessHandler handler = new TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler();
handler.setRedirectStrategy(vaadinRedirectStrategy());
handler.setDefaultTargetUrl("/UI/");
handler.setTargetUrlParameter("r");
return handler;
}
@Override
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) {
// 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, "
+ "please ensure to set allow from URIs");
}
// workaround regex: we need to exclude the URL /UI/HEARTBEAT here
// because we bound the
// vaadin application to /UI and not to root, described in
// vaadin-forum:
// https://vaadin.com/forum#!/thread/3200565.
HttpSecurity httpSec = http.regexMatcher("(?!.*HEARTBEAT)^.*\\/UI.*$")
// disable as CSRF is handled by Vaadin
.csrf().disable();
if (springSecurityProperties.isRequireSsl()) {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
} else {
LOG.info(
"\"******************\\n** Requires HTTPS Security has been disabled for UI, should only use for developing purposes **\\n******************\"");
}
// for UI integrator we allow frame integration on same origin
httpSec.headers()
.addHeaderWriter(confXframeOption.equals(XFAME_OPTION_ALLOW_FROM)
? new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI(confAllowFromUri)))
: new XFrameOptionsHeaderWriter(xframeOptionFromStr(confXframeOption)))
.contentTypeOptions().xssProtection().httpStrictTransportSecurity().and()
// UI
.authorizeRequests().antMatchers("/UI/login/**").permitAll().antMatchers("/UI/UIDL/**").permitAll()
.anyRequest().authenticated().and()
// UI login / logout
.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/UI/login/#/"))
.and().logout().logoutUrl("/UI/logout").logoutSuccessUrl("/UI/login/#/");
}
/**
* Converts a given string into the {@link XFrameOptionsMode} enum. Only
* {@link XFrameOptionsMode#DENY} and
* {@link XFrameOptionsMode#SAMEORIGIN} any other string will be
* converted to the default {@link XFrameOptionsMode#SAMEORIGIN}.
*
* @param xframeOption
* the string of the xframe option
* @return an {@link XFrameOptionsMode} by the given string, in case
* string does not match an option then
* {@link XFrameOptionsMode#SAMEORIGIN} is returned
*/
private XFrameOptionsMode xframeOptionFromStr(@NotNull final String xframeOption) {
switch (xframeOption) {
case XFRAME_OPTION_DENY:
return XFrameOptionsMode.DENY;
case XFRAME_OPTION_SAMEORIGIN:
// fall through to default because the same
default:
return XFrameOptionsMode.SAMEORIGIN;
}
}
@Override
public void configure(final WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**",
"/docs/**");
}
}
/**
* A Websecruity config to handle and filter the download ids.
*
*
*
*/
@Configuration
@EnableWebSecurity
@Order(200)
public static class IdRestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProperties securityConfiguration;
@Autowired
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
private Cache downloadIdCache;
@Override
protected void configure(final HttpSecurity http) throws Exception {
final HttpDownloadAuthenticationFilter downloadIdAuthenticationFilter = new HttpDownloadAuthenticationFilter(
downloadIdCache);
downloadIdAuthenticationFilter.setAuthenticationManager(authenticationManager());
http.csrf().disable();
http.anonymous().disable();
http.regexMatcher(HttpDownloadAuthenticationFilter.REQUEST_ID_REGEX_PATTERN)
.addFilterBefore(downloadIdAuthenticationFilter, FilterSecurityInterceptor.class);
http.authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
}
}
}
/**
* After a successful login on the UI we need to ensure to create the tenant
* meta data within SP.
*
*
*/
class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends VaadinUrlAuthenticationSuccessHandler {
@Autowired
private SystemManagement systemManagement;
/*
* (non-Javadoc)
*
* @see org.vaadin.spring.security.web.authentication.
* SavedRequestAwareVaadinAuthenticationSuccessHandler
* #onAuthenticationSuccess(org.springframework.security.core.
* Authentication)
*/
@Override
public void onAuthenticationSuccess(final Authentication authentication) throws Exception {
if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) {
systemManagement
.getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString());
} else if (authentication.getClass().equals(UsernamePasswordAuthenticationToken.class)) {
// TODO: MECS-1078 vaadin4spring-ext-security does not give us the
// fullyAuthenticatedToken
// in the GenericVaadinSecurity class. Only the token which has been
// created in the
// LoginView. This needs to be changed with the update of
// vaadin4spring 0.0.7 because it
// has been fixed.
systemManagement.getTenantMetadata("DEFAULT");
}
super.onAuthenticationSuccess(authentication);
}
}
/**
* Sevletfilter to create metadata after successful authentication over RESTful.
*
*
*/
class AuthenticationSuccessTenantMetadataCreationFilter implements Filter {
private final TenantAware tenantAware;
private final SystemManagement systemManagement;
AuthenticationSuccessTenantMetadataCreationFilter(final TenantAware tenantAware,
final SystemManagement systemManagement) {
this.tenantAware = tenantAware;
this.systemManagement = systemManagement;
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
// not needed
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final String currentTenant = tenantAware.getCurrentTenant();
if (currentTenant != null) {
// lazy initialize tenant meta data after successful authentication
systemManagement.getTenantMetadata(currentTenant);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
// not needed
}
}

View File

@@ -0,0 +1,93 @@
/**
* 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.swagger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.hawkbit.rest.resource.RestConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger configuration for RESTful SP server APIs.
*
*
*
*
*/
@Configuration
@EnableSwagger2
public class SwaggerApiDocAutoConfiguration {
/**
* Create the Springfox Docket, which generates the Information for the
* REST-Swagger-UI. Rest paths are: /rest/v1/. and ./controller/v1/.
*
* @see springfox.documentation.spring.web.plugins.Docket
*
* @return the v1 docket
*/
@Bean
public Docket customImplementation() {
return createDocket();
}
private Predicate<String> selectApiPaths() {
return Predicates.or(PathSelectors.regex("/rest/v1/.*"), PathSelectors.regex("/.*/controller/v1/.*"));
}
private Docket createDocket() {
final List<ResponseMessage> authorizationMessages = globalAuhtorizationMessages();
return new Docket(DocumentationType.SWAGGER_2).select().paths(selectApiPaths()).build()
.useDefaultResponseMessages(true).globalResponseMessage(RequestMethod.GET, authorizationMessages)
.globalResponseMessage(RequestMethod.POST, authorizationMessages)
.globalResponseMessage(RequestMethod.PUT, authorizationMessages)
.globalResponseMessage(RequestMethod.DELETE, authorizationMessages).apiInfo(apiInfo());
}
private List<ResponseMessage> globalAuhtorizationMessages() {
final List<ResponseMessage> messageList = new ArrayList<>();
messageList.add(new ResponseMessage(200, "Request sucessfull", new ModelRef("com.")));
messageList.add(new ResponseMessage(400, "Bad Request - e.g. invalid parameters", null));
messageList.add(new ResponseMessage(401, "Unauthorized - The request requires user authentication.",
null));
messageList.add(
new ResponseMessage(403, "Forbidden - Insufficient permissions or data volume restriction applies.",
new ModelRef("ExceptionInfo")));
messageList.add(new ResponseMessage(405, "Method Not Allowed", null));
messageList.add(new ResponseMessage(406,
"Not Acceptable - In case accept header is specified and not application/json", null));
messageList.add(new ResponseMessage(429,
"Too many requests. The server will refuse further attemps and the client has to wait another second.",
null));
return messageList;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Software Provisioning API Descriptions").version(RestConstants.API_VERSION)
.build();
}
}

View File

@@ -0,0 +1,40 @@
/**
* 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.ui;
import org.eclipse.hawkbit.DistributedResourceBundleMessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.vaadin.spring.annotation.EnableVaadinExtensions;
import org.vaadin.spring.events.annotation.EnableEventBus;
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
/**
* The hawkbit-ui autoconfiguration.
*
*
*
*/
@Configuration
@EnableVaadinSecurity
@EnableVaadinExtensions
@EnableEventBus
public class UIAutoConfiguration {
/**
* A message source bean to add distributed message sources.
*
* @return the message bean.
*/
@Bean(name = "messageSource")
public DistributedResourceBundleMessageSource messageSource() {
return new DistributedResourceBundleMessageSource();
}
}

View File

@@ -0,0 +1,55 @@
/**
* 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 java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.hawkbit.api.HostnameResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.base.Throwables;
/**
* Autoconfiguration of the {@link HostnameResolver} based on a property.
*
*
*
*/
@Configuration
@EnableConfigurationProperties(ServerProperties.class)
public class PropertyHostnameResolverAutoConfiguration {
@Autowired
private ServerProperties serverProperties;
/**
* @return the default autoconfigure hostname resolver implementation which
* is property based specified by the property {@link #url}
*/
@Bean
@ConditionalOnMissingBean(value = HostnameResolver.class)
public HostnameResolver hostnameResolver() {
return new HostnameResolver() {
@Override
public URL resolveHostname() {
try {
return new URL(serverProperties.getUrl());
} catch (final MalformedURLException e) {
throw Throwables.propagate(e);
}
}
};
}
}

View File

@@ -0,0 +1,30 @@
/**
* 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;
}
}

View File

@@ -0,0 +1,28 @@
/**
* 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.web;
import org.eclipse.hawkbit.controller.EnableDirectDeviceApi;
import org.eclipse.hawkbit.rest.resource.EnableRestResources;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Auto-Configuration for enabling the REST-Resources.
*
*
*
*/
@Configuration
@ConditionalOnClass({ EnableDirectDeviceApi.class, EnableRestResources.class })
@Import({ EnableDirectDeviceApi.class, EnableRestResources.class })
public class ResourceControllerAutoConfiguration {
}

View File

@@ -0,0 +1,53 @@
/**
* 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.web;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* A configuration bean which disables the {@code useSuffixPatternMatch} feature
* from Spring because it will truncate the dot in a REST URL which leads to
* problem in case a controllerId contains dots and is a path parameter or
* filename ending.
*
*
*/
@Configuration
public class WebMvcAutoConfiguration extends WebMvcConfigurerAdapter {
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
* #configurePathMatch
* (org.springframework.web.servlet.config.annotation.PathMatchConfigurer)
*/
@Override
public void configurePathMatch(final PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
configurer.setUseRegisteredSuffixPatternMatch(false);
}
/*
* (non-Javadoc)
*
* @see org.springframework.web.servlet.config.annotation.
* WebMvcConfigurerAdapter# configureContentNegotiation
* (org.springframework.web.servlet.config.annotation.
* ContentNegotiationConfigurer)
*/
@Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}

View File

@@ -0,0 +1,16 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.eclipse.hawkbit.autoconfigure.conf.DefaultPropertiesAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.ui.UIAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.security.SecurityAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.swagger.SwaggerApiDocAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.url.PropertyHostnameResolverAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.web.WebMvcAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.DownloadIdCacheAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.conf.ControllerPollAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration

View File

@@ -0,0 +1,57 @@
#
# 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
#
# Tomcat / Server
server.tomcat.compression=on
spring.http.gzip.mime-types=text/html,text/xml,text/plain,application/json,application/javascript,text/css,application/x-javascript,text/javascript,application/vnd.ms-fontobject,application/x-font-opentype,application/x-font-truetype,application/x-font-ttf,application/xml,font/eot,font/opentype,font/otf,image/svg+xml,image/vnd.microsoft.icon
server.tomcat.compressable-mime-types=${spring.http.gzip.mime-types}
spring.http.gzip.min-gzip-size=256
# JPA / Datasource
spring.jpa.eclipselink.eclipselink.weaving=false
spring.jpa.database=H2
spring.jpa.show-sql=false
spring.datasource.driverClassName=org.h2.Driver
# MongoDB for artifact-repository
spring.data.mongodb.uri=mongodb://localhost/artifactrepo
spring.data.mongo.repositories.enabled=true
# Flyway DDL
flyway.enabled=true
flyway.initOnMigrate=true
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
# Vaadin Servlet
vaadin.static.servlet.params.resourceCacheTime=${spring.resources.cache-period}
vaadin.static.servlet.params.productionMode=true
vaadin.servlet.params.productionMode=true
vaadin.servlet.params.resourceCacheTime=${spring.resources.cache-period}
vaadin.servlet.urlMapping=/UI/*
vaadin.servlet.params.heartbeatInterval=60
vaadin.servlet.params.closeIdleSessions=false
# Spring MVC
spring.mvc.favicon.enabled=false
# Defines the thread pool executor
hawkbit.threadpool.corethreads=5
hawkbit.threadpool.maxthreads=20
hawkbit.threadpool.idletimeout=10000
hawkbit.threadpool.queuesize=250
# Defines the polling time for the controllers in HH:MM:SS notation
hawkbit.controller.pollingTime=00:05:00
hawkbit.controller.pollingOverdueTime=00:05: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