Skip to content

Commit

Permalink
Merge pull request #109 from georchestra/preserve-host-header-forward…
Browse files Browse the repository at this point in the history
…ed-headers-strategy-framework

preserve host header + set forward-headers-strategy FRAMEWORK
  • Loading branch information
f-necas committed May 28, 2024
2 parents 04f5aa2 + 6d35e43 commit e331633
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
* {@link java.net.UnknownHostException} and {@link java.net.ConnectException}
* to {@link HttpStatus#SERVICE_UNAVAILABLE}
*/
class CustomErrorAttributes extends DefaultErrorAttributes {
public class CustomErrorAttributes extends DefaultErrorAttributes {

@Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Expand Down
2 changes: 2 additions & 0 deletions gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ server:
ssl:
enabled: false
#TODO: configure SSL with a self-signed certificate
forward-headers-strategy: FRAMEWORK

spring:
config:
Expand Down Expand Up @@ -52,6 +53,7 @@ spring:
- RemoveSecurityHeaders
# AddSecHeaders appends sec-* headers to proxied requests based on the currently authenticated user
- AddSecHeaders
- PreserveHostHeader
- ApplicationError
global-filter:
websocket-routing:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import org.georchestra.gateway.autoconfigure.app.CustomErrorAttributes;
import org.georchestra.gateway.autoconfigure.app.ErrorCustomizerAutoConfiguration;
import org.georchestra.gateway.security.ldap.extended.GeorchestraUserNamePasswordAuthenticationToken;
import org.junit.jupiter.api.Test;
Expand All @@ -39,6 +40,7 @@
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
Expand All @@ -59,6 +61,8 @@ class GeorchestraGatewayApplicationTests {
private @Autowired GeorchestraGatewayApplication application;
private @Autowired WebTestClient testClient;

private @Autowired ApplicationContext context;

@Test
void contextLoadsFromDatadir() {
assertEquals("src/test/resources/test-datadir", env.getProperty("georchestra.datadir"));
Expand Down Expand Up @@ -109,12 +113,13 @@ void makeSureWhoamiDoesNotProvideAnySensitiveInfo() {
void errorCustomizerReturnsServiceUnavailableInsteadOfServerError() {
Map<String, Route> routesById = routeLocator.getRoutes()
.collect(Collectors.toMap(Route::getId, Function.identity())).block();

assertThat(context.getBean(CustomErrorAttributes.class)).isNotNull();
Route testRoute = routesById.get("unknownHostRoute");
assertNotNull(testRoute);
assertThat(testRoute.getUri()).isEqualTo(URI.create("http://not.a.valid.host:80"));

testClient.get().uri("/path/to/unavailable/service").exchange().expectStatus()
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
testClient.get().uri("/path/to/unavailable/service")//
.header("Host", "localhost")//
.exchange().expectStatus().isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ protected void doStart() {
assertNotNull(context.getBean(JsonPayloadHeadersContributor.class));

testClient.get().uri("/echo/")//
.header("Host", "localhost")//
.header("Authorization", "Basic dGVzdGFkbWluOnRlc3RhZG1pbg==") // testadmin:testadmin
.exchange()//
.expectStatus()//
Expand All @@ -81,6 +82,7 @@ protected void doStart() {
gatewayConfig.getDefaultHeaders().setJsonOrganization(Optional.of(false));

testClient.get().uri("/echo/")//
.header("Host", "localhost")//
.header("Authorization", "Basic dGVzdGFkbWluOnRlc3RhZG1pbg==") // testadmin:testadmin
.exchange()//
.expectStatus()//
Expand All @@ -96,6 +98,7 @@ protected void doStart() {
gatewayConfig.getDefaultHeaders().setJsonOrganization(Optional.of(true));

testClient.get().uri("/echo/")//
.header("Host", "localhost")//
.header("Authorization", "Basic dGVzdGFkbWluOnRlc3RhZG1pbg==") // testadmin:testadmin
.exchange()//
.expectStatus()//
Expand All @@ -107,6 +110,7 @@ protected void doStart() {

public @Test void testSecOrgnamePresent() {
testClient.get().uri("/echo/")//
.header("Host", "localhost")//
.header("Authorization", "Basic dGVzdGFkbWluOnRlc3RhZG1pbg==") // testadmin:testadmin
.exchange()//
.expectStatus()//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@

package org.georchestra.gateway.security.accessrules;

import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.noContent;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;

import java.net.URI;

import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import lombok.extern.slf4j.Slf4j;
import org.georchestra.gateway.app.GeorchestraGatewayApplication;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -40,11 +36,9 @@
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.web.reactive.server.WebTestClient;

import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import java.net.URI;

import lombok.extern.slf4j.Slf4j;
import static com.github.tomakehurst.wiremock.client.WireMock.*;

/**
* Integration tests for {@link AccessRulesCustomizer} for the access rules in
Expand Down Expand Up @@ -133,8 +127,12 @@ private static void mockServiceTarget(DynamicPropertyRegistry registry, String s
.withHeader("sec-proxy", equalTo("true"))//
.willReturn(ok()));

testClient.get().uri("/header").exchange().expectStatus().isOk();
testClient.get().uri("/header/img/logo.png").exchange().expectStatus().isOk();
testClient.get().uri("/header")//
.header("Host", "localhost")//
.exchange().expectStatus().isOk();
testClient.get().uri("/header/img/logo.png")//
.header("Host", "localhost")//
.exchange().expectStatus().isOk();
}

/**
Expand Down Expand Up @@ -172,10 +170,12 @@ private static void mockServiceTarget(DynamicPropertyRegistry registry, String s
mockService.stubFor(get(urlMatching("/import(/.*)?")).willReturn(ok()));

testClient.get().uri("/import")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();

testClient.get().uri("/import/any/thing")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();
}
Expand Down Expand Up @@ -216,10 +216,12 @@ private static void mockServiceTarget(DynamicPropertyRegistry registry, String s
mockService.stubFor(get(urlMatching("/analytics(/.*)?")).willReturn(ok()));

testClient.get().uri("/analytics")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();

testClient.get().uri("/analytics/any/thing")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();
}
Expand Down Expand Up @@ -264,10 +266,12 @@ void testGlobalAccessRule() {
mockService.stubFor(get(urlMatching("/mapstore(/.*)?")).willReturn(ok()));

testClient.get().uri("/mapstore")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();

testClient.get().uri("/mapstore/any/thing")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();
}
Expand All @@ -281,6 +285,7 @@ void testQueryParamAuthentication_forbidden_when_anonymous() {
.expectStatus().is3xxRedirection();

testClient.get().uri("/header")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();
}
Expand All @@ -291,10 +296,12 @@ void testQueryParamAuthentication_authorized_if_logged_in() {
mockService.stubFor(get(urlMatching("/header(.*)?")).willReturn(ok()));

testClient.get().uri("/header?login")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();

testClient.get().uri("/header")//
.header("Host", "localhost")//
.exchange()//
.expectStatus().isOk();
}
Expand Down

0 comments on commit e331633

Please sign in to comment.