Commit 1c5abd58 by Johannes Edmeier

Only proxy whitelisted acuator endpoints

To not accidentally expose senstive urls only expose whitelisted management-endpoints via the zuul proxy filter.
parent 0db4fe16
......@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
......@@ -45,6 +46,8 @@ public class ApplicationRouteLocator implements RouteLocator {
private String prefix;
private PathMatcher pathMatcher = new AntPathMatcher();
private String servletPath;
private String[] proxyEndpoints = { "/env", "/metrics", "/trace", "/dump", "/jolokia", "/info",
"/configprops", "/trace", "/activiti", "/logfile", "/refresh" };
public ApplicationRouteLocator(String servletPath, ApplicationRegistry registry,
String prefix) {
......@@ -56,14 +59,15 @@ public class ApplicationRouteLocator implements RouteLocator {
private LinkedHashMap<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> locateRoutes = new LinkedHashMap<String, ZuulRoute>();
for (Application application : registry.getApplications()) {
addRoute(locateRoutes, prefix + "/" + application.getId() + "/health/**",
application.getHealthUrl());
String appPath = prefix + "/" + application.getId();
addRoute(locateRoutes, appPath + "/health/**", application.getHealthUrl());
if (!StringUtils.isEmpty(application.getManagementUrl())) {
addRoute(locateRoutes, prefix + "/" + application.getId() + "/*/**",
application.getManagementUrl());
for (String endpoint : proxyEndpoints) {
addRoute(locateRoutes, appPath + endpoint + "/**",
application.getManagementUrl() + endpoint);
}
}
}
return locateRoutes;
}
......@@ -72,7 +76,8 @@ public class ApplicationRouteLocator implements RouteLocator {
}
public ProxyRouteSpec getMatchingRoute(String path) {
LOGGER.info("Finding route for path: {}; servletPath={}", path, this.servletPath);
LOGGER.info("Finding route for path: {}", path);
LOGGER.debug("servletPath={}", this.servletPath);
if (StringUtils.hasText(this.servletPath) && !this.servletPath.equals("/")
&& path.startsWith(this.servletPath)) {
path = path.substring(this.servletPath.length());
......@@ -84,7 +89,7 @@ public class ApplicationRouteLocator implements RouteLocator {
ZuulRoute route = entry.getValue();
int index = route.getPath().indexOf("*") - 1;
String routePrefix = route.getPath().substring(0, index);
String targetPath = path.replaceFirst(routePrefix, "");
String targetPath = path.substring(index, path.length());
return new ProxyRouteSpec(route.getId(), targetPath, route.getLocation(),
routePrefix);
}
......@@ -118,6 +123,14 @@ public class ApplicationRouteLocator implements RouteLocator {
return Collections.emptyList();
}
public void setProxyEndpoints(String[] proxyEndpoints) {
for (String endpoint : proxyEndpoints) {
Assert.hasText(endpoint, "The proxyEndpoints must not contain null");
Assert.isTrue(endpoint.startsWith("/"), "All proxyEndpoints must start with '/'");
}
this.proxyEndpoints = proxyEndpoints.clone();
}
public static class ProxyRouteSpec {
private final String id;
private final String path;
......
......@@ -19,6 +19,7 @@ import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
......@@ -39,6 +40,7 @@ public class ApplicationRouteLocatorTest {
public void setup() {
registry = mock(ApplicationRegistry.class);
locator = new ApplicationRouteLocator("/", registry, "/api/applications");
locator.setProxyEndpoints(new String[] { "/env" });
}
@Test
......@@ -71,7 +73,7 @@ public class ApplicationRouteLocatorTest {
assertEquals(2, locator.getRoutes().size());
assertThat(locator.getRoutePaths(),
hasItems("/api/applications/1234/health/**", "/api/applications/1234/*/**"));
hasItems("/api/applications/1234/health/**", "/api/applications/1234/env/**"));
assertEquals("http://localhost/health",
locator.getRoutes().get("/api/applications/1234/health/**"));
......@@ -81,10 +83,12 @@ public class ApplicationRouteLocatorTest {
assertEquals("http://localhost/health", route.getLocation());
assertEquals("/api/applications/1234/health", route.getPrefix());
route = locator.getMatchingRoute("/api/applications/1234/notify");
assertEquals("api/applications/1234", route.getId());
assertEquals("/notify", route.getPath());
assertEquals("http://localhost", route.getLocation());
assertEquals("/api/applications/1234", route.getPrefix());
route = locator.getMatchingRoute("/api/applications/1234/env/reset");
assertEquals("api/applications/1234/env", route.getId());
assertEquals("/reset", route.getPath());
assertEquals("http://localhost/env", route.getLocation());
assertEquals("/api/applications/1234/env", route.getPrefix());
assertNull(locator.getMatchingRoute("/api/applications/1234/danger"));
}
}
......@@ -48,6 +48,7 @@ public class PreDecorationFilterTest {
.withManagementUrl("http://mgmt").build());
registry = new ApplicationRegistry(store, new HashingApplicationUrlIdGenerator());
routeLocator = new ApplicationRouteLocator("/", registry, "/proxied");
routeLocator.setProxyEndpoints(new String[] { "/foo" });
routeLocator.resetRoutes();
filter = new PreDecorationFilter(routeLocator, true);
RequestContext ctx = RequestContext.getCurrentContext();
......@@ -67,10 +68,10 @@ public class PreDecorationFilterTest {
request.setRequestURI("/proxied/-id-/foo");
filter.run();
RequestContext ctx = RequestContext.getCurrentContext();
assertEquals("/foo", ctx.get("requestURI"));
assertEquals("http://mgmt", ctx.getRouteHost().toString());
assertEquals("", ctx.get("requestURI"));
assertEquals("http://mgmt/foo", ctx.getRouteHost().toString());
assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host"));
assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto"));
assertEquals("/proxied/-id-", ctx.getZuulRequestHeaders().get("x-forwarded-prefix"));
assertEquals("/proxied/-id-/foo", ctx.getZuulRequestHeaders().get("x-forwarded-prefix"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment