diff --git a/hawkbit-repository/hawkbit-repository-test/pom.xml b/hawkbit-repository/hawkbit-repository-test/pom.xml
index 64989fc87..cbf4411a5 100644
--- a/hawkbit-repository/hawkbit-repository-test/pom.xml
+++ b/hawkbit-repository/hawkbit-repository-test/pom.xml
@@ -75,6 +75,10 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.security
+ spring-security-test
+
org.springframework
spring-context-support
diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java
index 22bdb4e5b..5db0499dd 100644
--- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java
+++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java
@@ -171,7 +171,7 @@ public class WithSpringAuthorityRule implements BeforeEachCallback, AfterEachCal
};
}
- private static class SecurityContextWithUser implements SecurityContext {
+ static class SecurityContextWithUser implements SecurityContext {
private static final long serialVersionUID = 1L;
private final WithUser annotation;
diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithUser.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithUser.java
index 5a58053ed..25d517071 100644
--- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithUser.java
+++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithUser.java
@@ -9,6 +9,10 @@
*/
package org.eclipse.hawkbit.repository.test.util;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.test.context.support.WithSecurityContext;
+import org.springframework.security.test.context.support.WithSecurityContextFactory;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
@@ -21,6 +25,7 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
+@WithSecurityContext(factory = WithUser.WithUserPrincipalSecurityContextFactory.class)
@Inherited
public @interface WithUser {
@@ -74,4 +79,11 @@ public @interface WithUser {
String[] removeFromAllPermission() default {};
boolean controller() default false;
-}
+
+ class WithUserPrincipalSecurityContextFactory implements WithSecurityContextFactory {
+ @Override
+ public SecurityContext createSecurityContext(final WithUser withUserPrincipal) {
+ return new WithSpringAuthorityRule.SecurityContextWithUser(withUserPrincipal);
+ }
+ }
+}
\ No newline at end of file
diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResourceTest.java
index 8fdc4c36d..d9451557f 100644
--- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResourceTest.java
+++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResourceTest.java
@@ -13,15 +13,41 @@ import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.qameta.allure.Story;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
+import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration;
+import org.eclipse.hawkbit.repository.test.TestConfiguration;
+import org.eclipse.hawkbit.repository.test.matcher.EventVerifier;
+import org.eclipse.hawkbit.repository.test.util.CleanupTestExecutionListener;
+import org.eclipse.hawkbit.repository.test.util.JUnitTestLoggerExtension;
+import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension;
+import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
+import org.eclipse.hawkbit.rest.RestConfiguration;
+import org.eclipse.hawkbit.rest.filter.ExcludePathAwareShallowETagFilter;
+import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.HttpHeaders;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.Base64Utils;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.filter.CharacterEncodingFilter;
+import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
+import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -30,24 +56,49 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
/**
* Test for {@link MgmtBasicAuthResource}.
- *
*/
+@ActiveProfiles({ "test" })
+@ExtendWith({ JUnitTestLoggerExtension.class, SharedSqlTestDatabaseExtension.class })
+@SpringBootTest
+// destroy the context after each test class because otherwise we get problem
+// when context is
+// refreshed we e.g. get two instances of CacheManager which leads to very
+// strange test failures.
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
+// Cleaning repository will fire "delete" events. We won't count them to the
+// test execution. So, the order execution between EventVerifier and Cleanup is
+// important!
+@TestExecutionListeners(listeners = { EventVerifier.class, CleanupTestExecutionListener.class },
+ mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
+@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
+@WebAppConfiguration
+@AutoConfigureMockMvc
+@ContextConfiguration(classes = { MgmtApiConfiguration.class, RestConfiguration.class,
+ RepositoryApplicationConfiguration.class, TestConfiguration.class,
+ TestSupportBinderAutoConfiguration.class })
+//@TestPropertySource(locations = "classpath:/mgmt-test.properties")
@Feature("Component Tests - Management API")
@Story("Basic auth Userinfo Resource")
-public class MgmtBasicAuthResourceTest extends AbstractManagementApiIntegrationTest{
+public class MgmtBasicAuthResourceTest {
private static final String TEST_USER = "testUser";
private static final String DEFAULT = "default";
- // Need another mockMvc to bypass the default Basic auth security
@Autowired
- MockMvc mockMvcWithSecurity;
+ MockMvc defaultMock;
+
+ @Autowired
+ private FilterHttpResponse filterHttpResponse;
+ @Autowired
+ private CharacterEncodingFilter characterEncodingFilter;
+ @Autowired
+ protected WebApplicationContext webApplicationContext;
@Test
@Description("Test of userinfo api with basic auth validation")
@WithUser(principal = TEST_USER)
public void validateBasicAuthWithUserDetails() throws Exception {
- mvc.perform(get(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING)).andDo(MockMvcResultPrinter.print())
+ withSecurityMock().perform(get(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING)).andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON_VALUE))
@@ -58,7 +109,7 @@ public class MgmtBasicAuthResourceTest extends AbstractManagementApiIntegrationT
@Test
@Description("Test of userinfo api with invalid basic auth fails")
public void validateBasicAuthFailsWithInvalidCredentials() throws Exception {
- mockMvcWithSecurity.perform(get(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING)
+ defaultMock.perform(get(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING)
.header(HttpHeaders.AUTHORIZATION, getBasicAuth("wrongUser", "wrongSecret")))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnauthorized());
@@ -67,4 +118,14 @@ public class MgmtBasicAuthResourceTest extends AbstractManagementApiIntegrationT
private String getBasicAuth(final String username, final String password) {
return "Basic " + Base64Utils.encodeToString((username + ":" + password).getBytes());
}
+
+ private MockMvc withSecurityMock() throws Exception {
+ return createMvcWebAppContext(webApplicationContext).build();
+ }
+
+ private DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) {
+ final DefaultMockMvcBuilder createMvcWebAppContext = MockMvcBuilders.webAppContextSetup(context);
+
+ return createMvcWebAppContext;
+ }
}
diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java b/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java
index bc3eebd8d..f41f4a595 100644
--- a/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java
+++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java
@@ -14,7 +14,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@@ -52,7 +51,7 @@ public class DDIStart {
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
- public static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
+ public static class MethodSecurityConfig {
}
}
diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java
index 5ca89511d..942ab9321 100644
--- a/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java
+++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java
@@ -14,7 +14,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@@ -52,7 +51,7 @@ public class MgmtServerStart {
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
- public static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
+ public static class MethodSecurityConfig {
}
}
diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/PreAuthorizeEnabledTest.java b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/PreAuthorizeEnabledTest.java
new file mode 100644
index 000000000..3b079b915
--- /dev/null
+++ b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/PreAuthorizeEnabledTest.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2023 Bosch.IO GmbH and others
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.hawkbit.app.mgmt;
+
+import io.qameta.allure.Description;
+import io.qameta.allure.Feature;
+import io.qameta.allure.Story;
+import org.eclipse.hawkbit.im.authentication.SpPermission;
+import org.eclipse.hawkbit.repository.test.util.WithUser;
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpStatus;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+
+@Feature("Integration Test - Security")
+@Story("PreAuthorized enabled")
+public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
+
+ @Test
+ @Description("Tests whether request fail if a role is forbidden for the user")
+ @WithUser(authorities = { SpPermission.READ_TARGET } )
+ public void failIfNoRole() throws Exception {
+ mvc.perform(get("/rest/v1/distributionsets")).andExpect(result ->
+ assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
+ }
+
+ @Test
+ @Description("Tests whether request succeed if a role is granted for the user")
+ @WithUser(authorities = { SpPermission.READ_REPOSITORY })
+ public void successIfHasRole() throws Exception {
+ mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> {
+ assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
+ });
+ }
+}
\ No newline at end of file
diff --git a/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/PreAuthorizeEnabledTest.java b/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/PreAuthorizeEnabledTest.java
new file mode 100644
index 000000000..6345d559b
--- /dev/null
+++ b/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/PreAuthorizeEnabledTest.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2023 Bosch.IO GmbH and others
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.hawkbit.app;
+
+import io.qameta.allure.Description;
+import io.qameta.allure.Feature;
+import io.qameta.allure.Story;
+import org.eclipse.hawkbit.im.authentication.SpPermission;
+import org.eclipse.hawkbit.repository.test.util.WithUser;
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpStatus;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+
+@Feature("Integration Test - Security")
+@Story("PreAuthorized enabled")
+public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
+
+ @Test
+ @Description("Tests whether request fail if a role is forbidden for the user")
+ @WithUser(authorities = { SpPermission.READ_TARGET } )
+ public void failIfNoRole() throws Exception {
+ mvc.perform(get("/rest/v1/distributionsets")).andExpect(result ->
+ assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
+ }
+
+ @Test
+ @Description("Tests whether request succeed if a role is granted for the user")
+ @WithUser(authorities = { SpPermission.READ_REPOSITORY })
+ public void successIfHasRole() throws Exception {
+ mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> {
+ assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
+ });
+ }
+}
\ No newline at end of file