diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/auth/MgmtUserInfo.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/auth/MgmtUserInfo.java new file mode 100644 index 000000000..0ebba1605 --- /dev/null +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/auth/MgmtUserInfo.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2021 Bosch.IO 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.mgmt.json.model.auth; + +/** + * A json annotated rest model for Userinfo to RESTful API representation. + * + */ +public class MgmtUserInfo { + + private String username; + private String tenant; + + /** + * @return Username + */ + public String getUsername() { + return username; + } + + /** + * @param username Username + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * @return Tenant + */ + public String getTenant() { + return tenant; + } + + /** + * @param tenant Tenant + */ + public void setTenant(String tenant) { + this.tenant = tenant; + } + +} \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtBasicAuthRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtBasicAuthRestApi.java new file mode 100644 index 000000000..394771628 --- /dev/null +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtBasicAuthRestApi.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2021 Bosch.IO 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.mgmt.rest.api; + +import org.eclipse.hawkbit.mgmt.json.model.auth.MgmtUserInfo; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Api for handling basic auth user validation + */ +@RequestMapping(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING) +public interface MgmtBasicAuthRestApi { + /** + * Handles the GET request of basic auth. + * + * @return the userinfo with status OK. + */ + @GetMapping(produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) + ResponseEntity validateBasicAuth(); +} diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java index 52a1a30ff..cbb7bf8ed 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java @@ -233,6 +233,11 @@ public final class MgmtRestConstants { public static final String DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES = "mandatorymoduletypes"; + /** + * The basic authentication validation mapping + */ + public static final String AUTH_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/userinfo"; + // constant class, private constructor. private MgmtRestConstants() { diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResource.java new file mode 100644 index 000000000..7cc655c70 --- /dev/null +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResource.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2021 Bosch.IO 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.mgmt.rest.resource; + +import org.eclipse.hawkbit.mgmt.json.model.auth.MgmtUserInfo; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtBasicAuthRestApi; +import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +/** + * REST Resource handling basic auth validation. + */ +@RestController +public class MgmtBasicAuthResource implements MgmtBasicAuthRestApi { + + private final TenantAware tenantAware; + + /** + * Default constructor + * + * @param tenantAware + * tenantAware + */ + public MgmtBasicAuthResource(TenantAware tenantAware) { + this.tenantAware = tenantAware; + } + + @Override + public ResponseEntity validateBasicAuth() { + MgmtUserInfo userInfo = new MgmtUserInfo(); + userInfo.setUsername(tenantAware.getCurrentUsername()); + userInfo.setTenant(tenantAware.getCurrentTenant()); + return ResponseEntity.ok(userInfo); + } +} 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 new file mode 100644 index 000000000..0b952a271 --- /dev/null +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtBasicAuthResourceTest.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2021 Bosch.IO 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.mgmt.rest.resource; + +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.test.util.WithUser; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.HttpHeaders; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.util.Base64Utils; + +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; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Test for {@link MgmtBasicAuthResource}. + * + */ +@Feature("Component Tests - Management API") +@Story("Basic auth Userinfo Resource") +public class MgmtBasicAuthResourceTest extends AbstractManagementApiIntegrationTest{ + + 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; + + @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()) + .andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaTypes.HAL_JSON_VALUE)) + .andExpect(jsonPath("$.username", equalTo(TEST_USER))) + .andExpect(jsonPath("$.tenant", equalTo(DEFAULT))); + } + + @Test + @Description("Test of userinfo api with invalid basic auth fails") + public void validateBasicAuthFailsWithInvalidCredentials() throws Exception { + mockMvcWithSecurity.perform(get(MgmtRestConstants.AUTH_V1_REQUEST_MAPPING) + .header(HttpHeaders.AUTHORIZATION, getBasicAuth("wrongUser", "wrongSecret"))) + .andDo(MockMvcResultPrinter.print()) + .andExpect(status().isUnauthorized()); + } + + private String getBasicAuth(final String username, final String password) { + return "Basic " + Base64Utils.encodeToString((username + ":" + password).getBytes()); + } +}