DosFilter can be disabled. (#561)

* DosFilter can be disabled.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Moved filters our of security core.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Move caffeine dependency.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2017-07-13 12:52:00 +02:00
committed by GitHub
parent 4c529dd755
commit 66feae2756
10 changed files with 54 additions and 39 deletions

View File

@@ -35,7 +35,6 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.DosFilter;
import org.eclipse.hawkbit.security.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateAnonymousDownloadFilter;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
@@ -51,6 +50,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
@@ -172,6 +172,7 @@ public class SecurityManagedConfiguration {
* of service protection filter in the filter chain
*/
@Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosDDiFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(Arrays.asList(DDI_ANT_MATCHER),
@@ -262,6 +263,7 @@ public class SecurityManagedConfiguration {
* service protection filter in the filter chain
*/
@Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosSystemFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(Collections.emptyList(),
@@ -355,6 +357,7 @@ public class SecurityManagedConfiguration {
* of service protection filter in the filter chain
*/
@Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosMgmtFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(null, securityProperties.getDos().getFilter(),
@@ -406,29 +409,6 @@ public class SecurityManagedConfiguration {
}
}
/**
* Filter registration bean for spring etag filter.
*
* @return the spring filter registration bean for registering an etag
* filter in the filter chain
*/
@Bean
@Order(380)
public FilterRegistrationBean eTagFilter() {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
// Exclude 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("/UI/**",
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download",
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/**",
"/api/v1/downloadserver/**"));
return filterRegBean;
}
/**
* {@link WebSecurityConfigurer} for external (management) access.
*/
@@ -457,6 +437,7 @@ public class SecurityManagedConfiguration {
* of service protection filter in the filter chain
*/
@Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.ui-filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosMgmtUiFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(null, securityProperties.getDos().getUiFilter(),

View File

@@ -19,9 +19,9 @@ import java.util.List;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.security.DosFilter;
import org.eclipse.hawkbit.security.ExcludePathAwareShallowETagFilter;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

View File

@@ -39,6 +39,10 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- Test -->

View File

@@ -11,10 +11,12 @@ package org.eclipse.hawkbit.rest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.rest.exception.ResponseExceptionHandler;
import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
import org.eclipse.hawkbit.rest.util.HttpResponseFactoryBean;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@@ -64,4 +66,26 @@ public class RestConfiguration {
ResponseExceptionHandler responseExceptionHandler() {
return new ResponseExceptionHandler();
}
/**
* Filter registration bean for spring etag filter.
*
* @return the spring filter registration bean for registering an etag
* filter in the filter chain
*/
@Bean
FilterRegistrationBean eTagFilter() {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
// Exclude 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("/UI/**",
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download",
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/**",
"/api/v1/downloadserver/**"));
return filterRegBean;
}
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.security;
package org.eclipse.hawkbit.rest.filter;
import java.io.IOException;

View File

@@ -10,8 +10,8 @@ package org.eclipse.hawkbit.rest;
import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
import org.eclipse.hawkbit.security.ExcludePathAwareShallowETagFilter;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.security;
package org.eclipse.hawkbit.rest.filter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mockingDetails;
@@ -21,6 +21,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

View File

@@ -31,14 +31,6 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>

View File

@@ -159,10 +159,15 @@ public class HawkbitSecurityProperties {
/**
* Configuration for hawkBits DOS prevention filter. This is usually an
* infrastructure topic but might be useful in some cases.
* infrastructure topic (e.g. Web Application Firewall (WAF)) but might
* be useful in some cases, e.g. to prevent unintended misuse.
*
*/
public static class Filter {
/**
* True if filter is enabled.
*/
private boolean enabled = true;
/**
* White list of peer IP addresses for DOS filter (regular
@@ -172,16 +177,24 @@ public class HawkbitSecurityProperties {
/**
* # Maximum number of allowed REST read/GET requests per second per
* client.
* client IP.
*/
int maxRead = 200;
/**
* Maximum number of allowed REST write/(PUT/POST/etc.) requests per
* second per client.
* second per client IP.
*/
int maxWrite = 50;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
public String getWhitelist() {
return whitelist;
}