Newer
Older
/*
* Copyright (c) 2024. Das Land Schleswig-Holstein vertreten durch das Ministerium für Energiewende, Klimaschutz, Umwelt und Natur
* Zentrales IT-Management
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
package de.ozgcloud.admin.security;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.apache.http.HttpHeaders;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import de.ozgcloud.common.test.DataITCase;
import lombok.SneakyThrows;
@DataITCase
@AutoConfigureMockMvc
@Autowired
private MockMvc mockMvc;
@DisplayName("without authorization")
@Nested
class TestWithoutAuthorization {
@DisplayName("allow for not found")
@SneakyThrows
@ParameterizedTest
@ValueSource(strings = {
"/actuator", "/actuator/x", "/actuator/x/y",
"/configserver", "/configserver/x",
})
void shouldAllowForNotFound(String path) {
var result = doPerform(path);
result.andExpect(status().isNotFound());
}
@DisplayName("allow")
@SneakyThrows
@ParameterizedTest
@ValueSource(strings = {
"/configserver/name/profile"
})
void shouldAllow(String path) {
var result = doPerform(path);
result.andExpect(status().isOk());
}
@SneakyThrows
@ParameterizedTest
@ValueSource(strings = {
"/api", "/api/configuration", "/api/configuration/param",
"/unknown",
})
void shouldDeny(String path) {
var result = doPerform(path);
result.andExpect(status().isUnauthorized());
}
@DisplayName("deny with problem details")
@Nested
class TestDenyWithProblemDetails {
@SneakyThrows
@Test
void shouldHaveStatus() {
var result = doPerform("/api");
result.andExpect(jsonPath("$.status").value(HttpStatus.UNAUTHORIZED.value()));
}
@SneakyThrows
@Test
void shouldHaveInstanceURI() {
var result = doPerform("/api");
result.andExpect(jsonPath("$.instance").value("/api"));
}
result.andExpect(jsonPath("$.detail").value("Full authentication is required to access this resource"));
@Test
@SneakyThrows
var result = doPerform("/api");
result.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer realm=\"Restricted Content\""));
}
@SneakyThrows
private ResultActions doPerform(String path) {
return mockMvc.perform(get(path).header("Authorization", "invalid"));
}
}
@DisplayName("with authorization")
@Nested
class TestWithAuthorization {
static final String CLAIMS = """
{
"preferredUsername": "testUser",
"scope": "openid testscope"
}""";
@SneakyThrows
@ParameterizedTest
@ValueSource(strings = {
"/configserver/name/profile",
"/api", "/api/configuration", "/api/configuration/param",
})
@WithJwt(CLAIMS)
void shouldAllow(String path) {
var result = doPerformAuthenticated(path);
result.andExpect(status().isOk());
}
@SneakyThrows
private ResultActions doPerformAuthenticated(String path) {
return mockMvc.perform(get(path));
}
}
}