diff --git a/gateway/src/main/resources/application.yml b/gateway/src/main/resources/application.yml index 1fc93b7e..3850640a 100644 --- a/gateway/src/main/resources/application.yml +++ b/gateway/src/main/resources/application.yml @@ -50,7 +50,7 @@ spring: - SecureHeaders - TokenRelay - RemoveSecurityHeaders - # AddSecHeaders appends sec-* headers to proxied requests based on the + # AddSecHeaders appends sec-* headers to proxied requests based on the currently authenticated user - AddSecHeaders global-filter: websocket-routing: diff --git a/gateway/src/test/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilterIT.java b/gateway/src/test/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilterIT.java new file mode 100644 index 00000000..5bf5e4f6 --- /dev/null +++ b/gateway/src/test/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilterIT.java @@ -0,0 +1,74 @@ +package org.georchestra.gateway.security; + +import org.georchestra.gateway.accounts.events.rabbitmq.RabbitmqAccountCreatedEventSender; +import org.georchestra.gateway.app.GeorchestraGatewayApplication; +import org.georchestra.gateway.filter.headers.providers.JsonPayloadHeadersContributor; +import org.georchestra.testcontainers.ldap.GeorchestraLdapContainer; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.testcontainers.Testcontainers; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@SpringBootTest(classes = GeorchestraGatewayApplication.class) +@AutoConfigureWebTestClient(timeout = "PT20S") +@ActiveProfiles("georheaders") +public class ResolveGeorchestraUserGlobalFilterIT { + + public static GeorchestraLdapContainer ldap = new GeorchestraLdapContainer(); + + private @Autowired WebTestClient testClient; + + private @Autowired ApplicationContext context; + + public static GenericContainer httpEcho = new GenericContainer( + DockerImageName.parse("ealen/echo-server") + ) { + @Override + protected void doStart() { + super.doStart(); + Integer mappedPort = this.getMappedPort(80); + System.setProperty("httpEchoHost", this.getHost()); + System.setProperty("httpEchoPort", mappedPort.toString()); + System.out.println("Automatically set system property httpEchoHost=" + this.getHost()); + System.out.println("Automatically set system property httpEchoPort=" + mappedPort); + } + }; + + public static @BeforeAll void startUpContainers() { + httpEcho.setExposedPorts(Arrays.asList(new Integer[]{ 80 })); + httpEcho.start(); + ldap.start(); + } + + public static @AfterAll void shutDownContainers() { + ldap.stop(); + httpEcho.stop(); + } + + public @Test void testReceivedHeadersAsJson() { + assertNotNull(context.getBean(JsonPayloadHeadersContributor.class)); + + testClient.get().uri("/echo/")// + .header("Authorization", "Basic dGVzdGFkbWluOnRlc3RhZG1pbg==") // testadmin:testadmin + .exchange()// + .expectStatus()// + .is2xxSuccessful()// + .expectBody()// + .jsonPath(".request.headers.sec-user").exists() + .jsonPath(".request.headers.sec-organization").exists(); + } +} diff --git a/gateway/src/test/resources/application-georheaders.yml b/gateway/src/test/resources/application-georheaders.yml new file mode 100644 index 00000000..411263ff --- /dev/null +++ b/gateway/src/test/resources/application-georheaders.yml @@ -0,0 +1,47 @@ +georchestra: + gateway: + default-headers: + # Default security headers to append to proxied requests + proxy: true + username: true + roles: true + org: true + orgname: true + jsonUser: true + jsonOrganization: true + security: + ldap: + default: + enabled: true + extended: true + url: ldap://${ldapHost}:${ldapPort}/ + baseDn: dc=georchestra,dc=org + adminDn: cn=admin,dc=georchestra,dc=org + adminPassword: secret + users: + rdn: ou=users + searchFilter: (uid={0}) + pendingUsersSearchBaseDN: ou=pendingusers + protectedUsers: geoserver_privileged_user + roles: + rdn: ou=roles + searchFilter: (member={0}) + protectedRoles: ADMINISTRATOR, EXTRACTORAPP, GN_.*, ORGADMIN, REFERENT, USER, SUPERUSER + orgs: + rdn: ou=orgs + orgTypes: Association,Company,NGO,Individual,Other + pendingOrgSearchBaseDN: ou=pendingorgs + services: + echo: + target: http://${httpEchoHost}:${httpEchoPort} + access-rules: + - intercept-url: /echo/** + anonymous: false +spring: + cloud: + gateway: + routes: + - id: echo + uri: http://${httpEchoHost}:${httpEchoPort} + predicates: + - Path=/echo/