Skip to content

Commit

Permalink
Merge pull request #7571 from mbosecke/cas
Browse files Browse the repository at this point in the history
[GEOS-11202] Respect proxy base URL when building CAS service URL.
  • Loading branch information
petersmythe committed May 14, 2024
2 parents b3a04c1 + c705688 commit 40d1008
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
Expand All @@ -24,13 +25,16 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.geoserver.ows.URLMangler;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.security.LogoutFilterChain;
import org.geoserver.security.config.SecurityNamedServiceConfig;
import org.geoserver.security.filter.GeoServerLogoutFilter;
import org.geoserver.security.filter.GeoServerPreAuthenticatedUserNameFilter;
import org.geoserver.security.impl.GeoServerRole;
import org.geoserver.security.impl.RoleCalculator;
import org.geotools.util.logging.Logging;
import org.jasig.cas.client.configuration.ConfigurationKeys;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.session.SingleSignOutHandler;
Expand Down Expand Up @@ -59,6 +63,8 @@
public class GeoServerCasAuthenticationFilter extends GeoServerPreAuthenticatedUserNameFilter
implements LogoutHandler {

private static final Logger LOGGER = Logging.getLogger(GeoServerCasAuthenticationFilter.class);

protected Cas20ProxyTicketValidator validator;
protected ServiceAuthenticationDetailsSource casAuthenticationDetailsSource;
protected String casLogoutURL;
Expand Down Expand Up @@ -136,14 +142,15 @@ protected Assertion getCASAssertion(HttpServletRequest request) {

protected static String retrieveService(HttpServletRequest request) {

String serviceBaseUrl = null;
String proxyBaseUrl = GeoServerExtensions.getProperty("PROXY_BASE_URL");
if (StringUtils.hasLength(proxyBaseUrl)) {
serviceBaseUrl = proxyBaseUrl;
} else {
serviceBaseUrl = request.getRequestURL().toString();
}
StringBuffer buff = new StringBuffer(serviceBaseUrl);
String requestBaseUrl = ResponseUtils.baseURL(request);
String requestPath = request.getRequestURI().substring(request.getContextPath().length());

// Will run the URL through various manglers, to handle proxying, etc.
String serviceBaseUrl =
ResponseUtils.buildURL(
requestBaseUrl, requestPath, null, URLMangler.URLType.SERVICE);

StringBuilder buff = new StringBuilder(serviceBaseUrl);

if (StringUtils.hasLength(request.getQueryString())) {
String query = request.getQueryString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/* (c) 2024 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.security.cas;

import static org.junit.Assert.assertEquals;

import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.ows.HTTPHeadersCollector;
import org.geoserver.ows.ProxifyingURLMangler;
import org.geoserver.test.GeoServerSystemTestSupport;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;

public class GeoServerCasAuthenticationFilterTest extends GeoServerSystemTestSupport {

@Test
public void testRetrieveServiceWithNoProxyBaseUrl() {
GeoServer geoServer = getGeoServer();
String oldValue = System.getProperty("PROXY_BASE_URL");
try {
setProxyBase(geoServer, null);
setSystemProperty("PROXY_BASE_URL", null);

MockHttpServletRequest request =
buildMockRequest(
"http",
"localhost",
8080,
"/geoserver",
"/geoserver/myworkspace/wms?SERVICE=WMS");

String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);

assertEquals("http://localhost:8080/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
} finally {
// Reset to make sure we don't interfere with other tests at all
setSystemProperty("PROXY_BASE_URL", oldValue);
}
}

@Test
public void testRetrieveServiceWithProxyBaseUrlSystemProperty() {

String oldValue = System.getProperty("PROXY_BASE_URL");
try {
setSystemProperty("PROXY_BASE_URL", "https://example.com/geoserver");

MockHttpServletRequest request =
buildMockRequest(
"http",
"localhost",
8080,
"/geoserver",
"/geoserver/myworkspace/wms?SERVICE=WMS");

String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);

assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
} finally {
// Reset to make sure we don't interfere with other tests at all
setSystemProperty("PROXY_BASE_URL", oldValue);
}
}

@Test
public void testRetrieveServiceWithProxyBaseUrlConfig() {
GeoServer geoServer = getGeoServer();
try {
setProxyBase(geoServer, "https://example.com/geoserver");

MockHttpServletRequest request =
buildMockRequest(
"http",
"localhost",
8080,
"/geoserver",
"/geoserver/myworkspace/wms?SERVICE=WMS");

String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);

assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
} finally {
setProxyBase(geoServer, null);
}
}

@Test
public void testRetrieveServiceWithProxyBaseUrlConfigAndParameterization() {
GeoServer geoServer = getGeoServer();
try {
setProxyBase(geoServer, "https://${X-Forwarded-Host}/geoserver");

MockHttpServletRequest request =
buildMockRequest(
"http",
"localhost",
8080,
"/geoserver",
"/geoserver/myworkspace/wms?SERVICE=WMS");

// Add headers
request.addHeader(
ProxifyingURLMangler.Headers.FORWARDED_HOST.asString(), "example.com");
HTTPHeadersCollector filter = new HTTPHeadersCollector();
filter.collectHeaders(request);

String serviceUrl = GeoServerCasAuthenticationFilter.retrieveService(request);

assertEquals("https://example.com/geoserver/myworkspace/wms?SERVICE=WMS", serviceUrl);
} finally {
setProxyBase(geoServer, null);
}
}

private MockHttpServletRequest buildMockRequest(
String scheme, String serverName, int port, String contextPath, String uri) {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setScheme(scheme);
request.setServerName(serverName);
request.setServerPort(port);
request.setContextPath(contextPath);
request.setRequestURI(uri);
return request;
}

private void setProxyBase(GeoServer gs, String s) {
final GeoServerInfo global = gs.getGlobal();
global.getSettings().setProxyBaseUrl(s);
global.getSettings().setUseHeadersProxyURL(s != null);
gs.save(global);
}

private void setSystemProperty(String key, String value) {
if (value == null) {
System.clearProperty(key);
} else {
System.setProperty(key, value);
}
}
}

0 comments on commit 40d1008

Please sign in to comment.