Skip to content

Commit 144c093

Browse files
authored
Not allow access to supervision endpoints (#118)
Signed-off-by: achour94 <[email protected]>
1 parent d317f17 commit 144c093

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Copyright (c) 2024, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.gateway.filters;
8+
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
12+
import org.springframework.core.Ordered;
13+
import org.springframework.http.HttpStatus;
14+
import org.springframework.stereotype.Component;
15+
import org.springframework.web.server.ServerWebExchange;
16+
import reactor.core.publisher.Mono;
17+
18+
import java.util.regex.Pattern;
19+
20+
/**
21+
* A global pre-filter that controls access to supervision endpoints in the API gateway.
22+
*
23+
* This filter inspects the incoming request path and blocks access to specific supervision
24+
* endpoints based on a predefined pattern. The filter is designed to enhance security by
25+
* restricting access to potentially sensitive supervision functionalities.
26+
*
27+
* The filter blocks access to paths matching the following pattern:
28+
* {@code /v<number>/supervision} or {@code /v<number>/supervision/<any-sub-path>}
29+
* where {@code <number>} can be any positive integer representing the API version.
30+
*
31+
* Examples of blocked paths:
32+
* - /v1/supervision
33+
* - /v2/supervision/
34+
* - /v10/supervision/health
35+
* - /v999/supervision/metrics
36+
*
37+
* When a matching path is detected, the filter responds with a 403 Forbidden status.
38+
*
39+
* @author Achour BERRAHMA <achour.berrahma at rte-france.com>
40+
*/
41+
@Component
42+
public class SupervisionAccessControlFilter extends AbstractGlobalPreFilter {
43+
44+
private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionAccessControlFilter.class);
45+
private static final Pattern SUPERVISION_PATTERN = Pattern.compile("^/v\\d+/supervision(/.*)?$");
46+
public static final String ACCESS_TO_SUPERVISION_ENDPOINT_IS_NOT_ALLOWED = "{}: 403 Forbidden, Access to supervision endpoint is not allowed";
47+
48+
@Override
49+
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
50+
String path = exchange.getRequest().getURI().getPath();
51+
if (SUPERVISION_PATTERN.matcher(path).matches()) {
52+
LOGGER.info(ACCESS_TO_SUPERVISION_ENDPOINT_IS_NOT_ALLOWED,
53+
exchange.getRequest().getPath());
54+
return completeWithCode(exchange, HttpStatus.FORBIDDEN);
55+
}
56+
57+
return chain.filter(exchange);
58+
}
59+
60+
@Override
61+
public int getOrder() {
62+
// Execute after TokenValidatorGlobalPreFilter and UserAdminControlGlobalPreFilter
63+
return Ordered.LOWEST_PRECEDENCE - 2;
64+
}
65+
}

src/test/java/org/gridsuite/gateway/ElementAccessControlTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,28 @@ public void testDeleteElements() {
552552
.expectStatus().isOk();
553553
}
554554

555+
@Test
556+
public void testSupervisionEndpointsAccess() {
557+
initStubForJwk();
558+
559+
// Test access to a supervision endpoint (should be forbidden)
560+
webClient.get().uri("study/v1/supervision/studies")
561+
.header("Authorization", "Bearer " + tokenUser1)
562+
.exchange()
563+
.expectStatus().isForbidden();
564+
565+
// Test access to an endpoint containing 'supervision' but not matching the blocked pattern
566+
// This should pass through the filter
567+
stubFor(get(urlEqualTo("/v1/studies/supervision-report"))
568+
.withHeader("userId", equalTo("user1"))
569+
.willReturn(aResponse().withStatus(200)));
570+
571+
webClient.get().uri("study/v1/studies/supervision-report")
572+
.header("Authorization", "Bearer " + tokenUser1)
573+
.exchange()
574+
.expectStatus().isOk();
575+
}
576+
555577
@Test
556578
public void testAccessControlInfos() {
557579
List<UUID> emptyList = List.of();

0 commit comments

Comments
 (0)