Added test for DoSFilter.
Signed-off-by: Kai Zimmermann <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.ddi.rest.resource;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.AbstractRestIntegrationTest;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test potential DOS attack scenarios and check if the filter prevents them.
|
||||
*
|
||||
*/
|
||||
@ActiveProfiles({ "test" })
|
||||
@Features("Component Tests - REST Security")
|
||||
@Stories("Denial of Service protection filter")
|
||||
public class DosFilterTest extends AbstractRestIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that clients that are on the blacklist are forbidded ")
|
||||
public void blackListedClientIsForbidden() throws Exception {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 ")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a READ DoS attempt is blocked ")
|
||||
public void getFloddingAttackThatisPrevented() throws Exception {
|
||||
|
||||
MvcResult result = null;
|
||||
|
||||
int requests = 0;
|
||||
do {
|
||||
result = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")).andReturn();
|
||||
requests++;
|
||||
|
||||
// we give up after 10.000 requests
|
||||
assertThat(requests).isLessThan(10_000);
|
||||
} while (result.getResponse().getStatus() != HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
|
||||
// the filter shuts down after 100 GET requests
|
||||
assertThat(requests).isGreaterThanOrEqualTo(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv4 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
|
||||
for (int i = 0; i < 1_000; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "127.0.0.1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv6 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
|
||||
for (int i = 0; i < 1_000; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "0:0:0:0:0:0:0:1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptableGetLoad() throws Exception {
|
||||
|
||||
for (int x = 0; x < 3; x++) {
|
||||
// sleep for one second
|
||||
Thread.sleep(1100);
|
||||
for (int i = 0; i < 99; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a WRITE DoS attempt is blocked ")
|
||||
public void putPostFloddingAttackThatisPrevented() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
MvcResult result = null;
|
||||
int requests = 0;
|
||||
do {
|
||||
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||
tenantAware.getCurrentTenant()).header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1").content(feedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
requests++;
|
||||
|
||||
// we give up after 500 requests
|
||||
assertThat(requests).isLessThan(500);
|
||||
} while (result.getResponse().getStatus() != HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
|
||||
// the filter shuts down after 10 POST requests
|
||||
assertThat(requests).isGreaterThanOrEqualTo(10);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptablePutPostLoad() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
for (int x = 0; x < 5; x++) {
|
||||
// sleep for one second
|
||||
Thread.sleep(1100);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||
tenantAware.getCurrentTenant()).header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")
|
||||
.content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Long prepareDeploymentBase() {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("test");
|
||||
final Target target = targetManagement.createTarget(entityFactory.generateTarget("4711"));
|
||||
final List<Target> toAssign = new ArrayList<>();
|
||||
toAssign.add(target);
|
||||
|
||||
final Iterable<Target> saved = deploymentManagement.assignDistributionSet(ds, toAssign).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(target)).hasSize(1);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(target).get(0);
|
||||
|
||||
return uaction.getId();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user