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

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