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; ...@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.util.AntPathMatcher; import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.PathMatcher; import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
...@@ -45,6 +46,8 @@ public class ApplicationRouteLocator implements RouteLocator { ...@@ -45,6 +46,8 @@ public class ApplicationRouteLocator implements RouteLocator {
private String prefix; private String prefix;
private PathMatcher pathMatcher = new AntPathMatcher(); private PathMatcher pathMatcher = new AntPathMatcher();
private String servletPath; private String servletPath;
private String[] proxyEndpoints = { "/env", "/metrics", "/trace", "/dump", "/jolokia", "/info",
"/configprops", "/trace", "/activiti", "/logfile", "/refresh" };
public ApplicationRouteLocator(String servletPath, ApplicationRegistry registry, public ApplicationRouteLocator(String servletPath, ApplicationRegistry registry,
String prefix) { String prefix) {
...@@ -56,14 +59,15 @@ public class ApplicationRouteLocator implements RouteLocator { ...@@ -56,14 +59,15 @@ public class ApplicationRouteLocator implements RouteLocator {
private LinkedHashMap<String, ZuulRoute> locateRoutes() { private LinkedHashMap<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> locateRoutes = new LinkedHashMap<String, ZuulRoute>(); LinkedHashMap<String, ZuulRoute> locateRoutes = new LinkedHashMap<String, ZuulRoute>();
for (Application application : registry.getApplications()) { for (Application application : registry.getApplications()) {
addRoute(locateRoutes, prefix + "/" + application.getId() + "/health/**", String appPath = prefix + "/" + application.getId();
application.getHealthUrl()); addRoute(locateRoutes, appPath + "/health/**", application.getHealthUrl());
if (!StringUtils.isEmpty(application.getManagementUrl())) { if (!StringUtils.isEmpty(application.getManagementUrl())) {
addRoute(locateRoutes, prefix + "/" + application.getId() + "/*/**", for (String endpoint : proxyEndpoints) {
application.getManagementUrl()); addRoute(locateRoutes, appPath + endpoint + "/**",
application.getManagementUrl() + endpoint);
}
} }
} }
return locateRoutes; return locateRoutes;
} }
...@@ -72,7 +76,8 @@ public class ApplicationRouteLocator implements RouteLocator { ...@@ -72,7 +76,8 @@ public class ApplicationRouteLocator implements RouteLocator {
} }
public ProxyRouteSpec getMatchingRoute(String path) { 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("/") if (StringUtils.hasText(this.servletPath) && !this.servletPath.equals("/")
&& path.startsWith(this.servletPath)) { && path.startsWith(this.servletPath)) {
path = path.substring(this.servletPath.length()); path = path.substring(this.servletPath.length());
...@@ -84,7 +89,7 @@ public class ApplicationRouteLocator implements RouteLocator { ...@@ -84,7 +89,7 @@ public class ApplicationRouteLocator implements RouteLocator {
ZuulRoute route = entry.getValue(); ZuulRoute route = entry.getValue();
int index = route.getPath().indexOf("*") - 1; int index = route.getPath().indexOf("*") - 1;
String routePrefix = route.getPath().substring(0, index); 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(), return new ProxyRouteSpec(route.getId(), targetPath, route.getLocation(),
routePrefix); routePrefix);
} }
...@@ -118,6 +123,14 @@ public class ApplicationRouteLocator implements RouteLocator { ...@@ -118,6 +123,14 @@ public class ApplicationRouteLocator implements RouteLocator {
return Collections.emptyList(); 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 { public static class ProxyRouteSpec {
private final String id; private final String id;
private final String path; private final String path;
......
...@@ -19,6 +19,7 @@ import static java.util.Collections.singleton; ...@@ -19,6 +19,7 @@ import static java.util.Collections.singleton;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.CoreMatchers.hasItems;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
...@@ -39,6 +40,7 @@ public class ApplicationRouteLocatorTest { ...@@ -39,6 +40,7 @@ public class ApplicationRouteLocatorTest {
public void setup() { public void setup() {
registry = mock(ApplicationRegistry.class); registry = mock(ApplicationRegistry.class);
locator = new ApplicationRouteLocator("/", registry, "/api/applications"); locator = new ApplicationRouteLocator("/", registry, "/api/applications");
locator.setProxyEndpoints(new String[] { "/env" });
} }
@Test @Test
...@@ -71,7 +73,7 @@ public class ApplicationRouteLocatorTest { ...@@ -71,7 +73,7 @@ public class ApplicationRouteLocatorTest {
assertEquals(2, locator.getRoutes().size()); assertEquals(2, locator.getRoutes().size());
assertThat(locator.getRoutePaths(), assertThat(locator.getRoutePaths(),
hasItems("/api/applications/1234/health/**", "/api/applications/1234/*/**")); hasItems("/api/applications/1234/health/**", "/api/applications/1234/env/**"));
assertEquals("http://localhost/health", assertEquals("http://localhost/health",
locator.getRoutes().get("/api/applications/1234/health/**")); locator.getRoutes().get("/api/applications/1234/health/**"));
...@@ -81,10 +83,12 @@ public class ApplicationRouteLocatorTest { ...@@ -81,10 +83,12 @@ public class ApplicationRouteLocatorTest {
assertEquals("http://localhost/health", route.getLocation()); assertEquals("http://localhost/health", route.getLocation());
assertEquals("/api/applications/1234/health", route.getPrefix()); assertEquals("/api/applications/1234/health", route.getPrefix());
route = locator.getMatchingRoute("/api/applications/1234/notify"); route = locator.getMatchingRoute("/api/applications/1234/env/reset");
assertEquals("api/applications/1234", route.getId()); assertEquals("api/applications/1234/env", route.getId());
assertEquals("/notify", route.getPath()); assertEquals("/reset", route.getPath());
assertEquals("http://localhost", route.getLocation()); assertEquals("http://localhost/env", route.getLocation());
assertEquals("/api/applications/1234", route.getPrefix()); assertEquals("/api/applications/1234/env", route.getPrefix());
assertNull(locator.getMatchingRoute("/api/applications/1234/danger"));
} }
} }
...@@ -48,6 +48,7 @@ public class PreDecorationFilterTest { ...@@ -48,6 +48,7 @@ public class PreDecorationFilterTest {
.withManagementUrl("http://mgmt").build()); .withManagementUrl("http://mgmt").build());
registry = new ApplicationRegistry(store, new HashingApplicationUrlIdGenerator()); registry = new ApplicationRegistry(store, new HashingApplicationUrlIdGenerator());
routeLocator = new ApplicationRouteLocator("/", registry, "/proxied"); routeLocator = new ApplicationRouteLocator("/", registry, "/proxied");
routeLocator.setProxyEndpoints(new String[] { "/foo" });
routeLocator.resetRoutes(); routeLocator.resetRoutes();
filter = new PreDecorationFilter(routeLocator, true); filter = new PreDecorationFilter(routeLocator, true);
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
...@@ -67,10 +68,10 @@ public class PreDecorationFilterTest { ...@@ -67,10 +68,10 @@ public class PreDecorationFilterTest {
request.setRequestURI("/proxied/-id-/foo"); request.setRequestURI("/proxied/-id-/foo");
filter.run(); filter.run();
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
assertEquals("/foo", ctx.get("requestURI")); assertEquals("", ctx.get("requestURI"));
assertEquals("http://mgmt", ctx.getRouteHost().toString()); assertEquals("http://mgmt/foo", ctx.getRouteHost().toString());
assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host")); assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host"));
assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto")); 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