Skip to content
This repository was archived by the owner on Jun 29, 2018. It is now read-only.

Commit 1c5abd5

Browse files
committed
Only proxy whitelisted acuator endpoints
To not accidentally expose senstive urls only expose whitelisted management-endpoints via the zuul proxy filter.
1 parent 0db4fe1 commit 1c5abd5

3 files changed

Lines changed: 34 additions & 16 deletions

File tree

spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/zuul/ApplicationRouteLocator.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
2828
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
2929
import org.springframework.util.AntPathMatcher;
30+
import org.springframework.util.Assert;
3031
import org.springframework.util.PathMatcher;
3132
import org.springframework.util.StringUtils;
3233

@@ -45,6 +46,8 @@ public class ApplicationRouteLocator implements RouteLocator {
4546
private String prefix;
4647
private PathMatcher pathMatcher = new AntPathMatcher();
4748
private String servletPath;
49+
private String[] proxyEndpoints = { "/env", "/metrics", "/trace", "/dump", "/jolokia", "/info",
50+
"/configprops", "/trace", "/activiti", "/logfile", "/refresh" };
4851

4952
public ApplicationRouteLocator(String servletPath, ApplicationRegistry registry,
5053
String prefix) {
@@ -56,14 +59,15 @@ public ApplicationRouteLocator(String servletPath, ApplicationRegistry registry,
5659
private LinkedHashMap<String, ZuulRoute> locateRoutes() {
5760
LinkedHashMap<String, ZuulRoute> locateRoutes = new LinkedHashMap<String, ZuulRoute>();
5861
for (Application application : registry.getApplications()) {
59-
addRoute(locateRoutes, prefix + "/" + application.getId() + "/health/**",
60-
application.getHealthUrl());
62+
String appPath = prefix + "/" + application.getId();
63+
addRoute(locateRoutes, appPath + "/health/**", application.getHealthUrl());
6164
if (!StringUtils.isEmpty(application.getManagementUrl())) {
62-
addRoute(locateRoutes, prefix + "/" + application.getId() + "/*/**",
63-
application.getManagementUrl());
65+
for (String endpoint : proxyEndpoints) {
66+
addRoute(locateRoutes, appPath + endpoint + "/**",
67+
application.getManagementUrl() + endpoint);
68+
}
6469
}
6570
}
66-
6771
return locateRoutes;
6872
}
6973

@@ -72,7 +76,8 @@ private void addRoute(LinkedHashMap<String, ZuulRoute> locateRoutes, String path
7276
}
7377

7478
public ProxyRouteSpec getMatchingRoute(String path) {
75-
LOGGER.info("Finding route for path: {}; servletPath={}", path, this.servletPath);
79+
LOGGER.info("Finding route for path: {}", path);
80+
LOGGER.debug("servletPath={}", this.servletPath);
7681
if (StringUtils.hasText(this.servletPath) && !this.servletPath.equals("/")
7782
&& path.startsWith(this.servletPath)) {
7883
path = path.substring(this.servletPath.length());
@@ -84,7 +89,7 @@ public ProxyRouteSpec getMatchingRoute(String path) {
8489
ZuulRoute route = entry.getValue();
8590
int index = route.getPath().indexOf("*") - 1;
8691
String routePrefix = route.getPath().substring(0, index);
87-
String targetPath = path.replaceFirst(routePrefix, "");
92+
String targetPath = path.substring(index, path.length());
8893
return new ProxyRouteSpec(route.getId(), targetPath, route.getLocation(),
8994
routePrefix);
9095
}
@@ -118,6 +123,14 @@ public Collection<String> getIgnoredPaths() {
118123
return Collections.emptyList();
119124
}
120125

126+
public void setProxyEndpoints(String[] proxyEndpoints) {
127+
for (String endpoint : proxyEndpoints) {
128+
Assert.hasText(endpoint, "The proxyEndpoints must not contain null");
129+
Assert.isTrue(endpoint.startsWith("/"), "All proxyEndpoints must start with '/'");
130+
}
131+
this.proxyEndpoints = proxyEndpoints.clone();
132+
}
133+
121134
public static class ProxyRouteSpec {
122135
private final String id;
123136
private final String path;

spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/zuul/ApplicationRouteLocatorTest.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static java.util.Collections.singletonList;
2020
import static org.hamcrest.CoreMatchers.hasItems;
2121
import static org.junit.Assert.assertEquals;
22+
import static org.junit.Assert.assertNull;
2223
import static org.junit.Assert.assertThat;
2324
import static org.mockito.Mockito.mock;
2425
import static org.mockito.Mockito.when;
@@ -39,6 +40,7 @@ public class ApplicationRouteLocatorTest {
3940
public void setup() {
4041
registry = mock(ApplicationRegistry.class);
4142
locator = new ApplicationRouteLocator("/", registry, "/api/applications");
43+
locator.setProxyEndpoints(new String[] { "/env" });
4244
}
4345

4446
@Test
@@ -71,7 +73,7 @@ public void locateRoutes() {
7173
assertEquals(2, locator.getRoutes().size());
7274

7375
assertThat(locator.getRoutePaths(),
74-
hasItems("/api/applications/1234/health/**", "/api/applications/1234/*/**"));
76+
hasItems("/api/applications/1234/health/**", "/api/applications/1234/env/**"));
7577

7678
assertEquals("http://localhost/health",
7779
locator.getRoutes().get("/api/applications/1234/health/**"));
@@ -81,10 +83,12 @@ public void locateRoutes() {
8183
assertEquals("http://localhost/health", route.getLocation());
8284
assertEquals("/api/applications/1234/health", route.getPrefix());
8385

84-
route = locator.getMatchingRoute("/api/applications/1234/notify");
85-
assertEquals("api/applications/1234", route.getId());
86-
assertEquals("/notify", route.getPath());
87-
assertEquals("http://localhost", route.getLocation());
88-
assertEquals("/api/applications/1234", route.getPrefix());
86+
route = locator.getMatchingRoute("/api/applications/1234/env/reset");
87+
assertEquals("api/applications/1234/env", route.getId());
88+
assertEquals("/reset", route.getPath());
89+
assertEquals("http://localhost/env", route.getLocation());
90+
assertEquals("/api/applications/1234/env", route.getPrefix());
91+
92+
assertNull(locator.getMatchingRoute("/api/applications/1234/danger"));
8993
}
9094
}

spring-boot-admin-server/src/test/java/de/codecentric/boot/admin/zuul/PreDecorationFilterTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void init() {
4848
.withManagementUrl("http://mgmt").build());
4949
registry = new ApplicationRegistry(store, new HashingApplicationUrlIdGenerator());
5050
routeLocator = new ApplicationRouteLocator("/", registry, "/proxied");
51+
routeLocator.setProxyEndpoints(new String[] { "/foo" });
5152
routeLocator.resetRoutes();
5253
filter = new PreDecorationFilter(routeLocator, true);
5354
RequestContext ctx = RequestContext.getCurrentContext();
@@ -67,10 +68,10 @@ public void prefixRouteAddsHeader() throws Exception {
6768
request.setRequestURI("/proxied/-id-/foo");
6869
filter.run();
6970
RequestContext ctx = RequestContext.getCurrentContext();
70-
assertEquals("/foo", ctx.get("requestURI"));
71-
assertEquals("http://mgmt", ctx.getRouteHost().toString());
71+
assertEquals("", ctx.get("requestURI"));
72+
assertEquals("http://mgmt/foo", ctx.getRouteHost().toString());
7273
assertEquals("localhost:80", ctx.getZuulRequestHeaders().get("x-forwarded-host"));
7374
assertEquals("http", ctx.getZuulRequestHeaders().get("x-forwarded-proto"));
74-
assertEquals("/proxied/-id-", ctx.getZuulRequestHeaders().get("x-forwarded-prefix"));
75+
assertEquals("/proxied/-id-/foo", ctx.getZuulRequestHeaders().get("x-forwarded-prefix"));
7576
}
7677
}

0 commit comments

Comments
 (0)