/* * Copyright 2014 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package netflix.adminresources; import static org.junit.Assert.assertEquals; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import com.google.inject.Guice; import com.google.inject.Injector; import com.netflix.config.ConfigurationManager; import netflix.admin.AdminConfigImpl; import netflix.admin.RedirectRules; public class AdminResourceTest { @Path("/ping") @Produces(MediaType.TEXT_HTML) public static class PingResource { @GET public Response ping() { return Response.ok().entity("pong").build(); } } static class AdminResourcesFixture implements AutoCloseable { @Inject private AdminResourcesContainer container; @Inject @Named(KaryonAdminModule.ADMIN_RESOURCES_SERVER_PORT) private int serverPort; public void close() { container.shutdown(); } } public AdminResourcesFixture adminTestFixture() throws Exception { final Injector appInjector = Guice.createInjector(new KaryonAdminModule() { @Override protected void configure() { bind(RedirectRules.class).toInstance(new RedirectRules() { @Override public Map<String, String> getMappings() { Map<String, String> routes = new HashMap<>(); routes.put("/", "/bad-route"); routes.put("/check-me", "/jr/ping"); routes.put("/auth/ping", "/jr/ping"); return routes; } @Override public String getRedirect(HttpServletRequest httpServletRequest) { final String requestURI = httpServletRequest.getRequestURI(); if (requestURI.startsWith("/proxy-ping")) { return "/jr/ping"; } return null; } }); } }); AdminResourcesContainer adminResourcesContainer = appInjector.getInstance(AdminResourcesContainer.class); adminResourcesContainer.init(); return appInjector.getInstance(AdminResourcesFixture.class); } @BeforeClass public static void init() { setConfig(AdminConfigImpl.CONTAINER_LISTEN_PORT, "0"); setConfig(AdminConfigImpl.NETFLIX_ADMIN_RESOURCE_CONTEXT, "/jr"); setConfig(AdminConfigImpl.NETFLIX_ADMIN_TEMPLATE_CONTEXT, "/main"); } @AfterClass public static void cleanup() { final AbstractConfiguration configInst = ConfigurationManager.getConfigInstance(); configInst.clearProperty(AdminConfigImpl.CONTAINER_LISTEN_PORT); } private static void setConfig(String name, String value) { ConfigurationManager.getConfigInstance().setProperty(name, value); } private static void enableAdminConsole() { ConfigurationManager.getConfigInstance().setProperty(AdminConfigImpl.SERVER_ENABLE_PROP_NAME, true); } private static void disableAdminConsole() { ConfigurationManager.getConfigInstance().setProperty(AdminConfigImpl.SERVER_ENABLE_PROP_NAME, false); } @Test public void checkPing() throws Exception { try (AdminResourcesFixture testFixture = adminTestFixture()) { HttpClient client = new DefaultHttpClient(); HttpGet healthGet = new HttpGet(String.format("http://localhost:%d/jr/ping", testFixture.serverPort)); HttpResponse response = client.execute(healthGet); assertEquals("admin resource ping resource failed.", 200, response.getStatusLine().getStatusCode()); } } @Test public void checkAuthFilter() throws Exception { setConfig(AdminConfigImpl.NETFLIX_ADMIN_CTX_FILTERS, "netflix.adminresources.AuthFilter"); try (AdminResourcesFixture testFixture = adminTestFixture()) { HttpClient client = new DefaultHttpClient(); HttpGet healthGet = new HttpGet(String.format("http://localhost:%d/jr/ping", testFixture.serverPort)); HttpResponse response = client.execute(healthGet); assertEquals("admin resource ping resource failed.", 200, response.getStatusLine().getStatusCode()); consumeResponse(response); healthGet = new HttpGet(String.format("http://localhost:%d/main/get-user-id", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource ping resource failed.", 403, response.getStatusLine().getStatusCode()); consumeResponse(response); healthGet = new HttpGet(String.format("http://localhost:%d/auth/no-page", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource ping resource failed.", 404, response.getStatusLine().getStatusCode()); consumeResponse(response); healthGet = new HttpGet(String.format("http://localhost:%d/foo/ping", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource ping resource failed.", 404, response.getStatusLine().getStatusCode()); consumeResponse(response); // verify redirect filter gets applied healthGet = new HttpGet(String.format("http://localhost:%d/check-me", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource did not pick a custom redirect routing", 200, response.getStatusLine().getStatusCode()); BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); assertEquals("ping resource did not return pong", br.readLine(), "pong"); // verify auth filter not applied to a potential redirect path healthGet = new HttpGet(String.format("http://localhost:%d/auth/ping", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource did not pick a custom redirect routing", 200, response.getStatusLine().getStatusCode()); br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); assertEquals("ping resource did not return pong", br.readLine(), "pong"); } finally { final AbstractConfiguration configInst = ConfigurationManager.getConfigInstance(); configInst.clearProperty(AdminConfigImpl.NETFLIX_ADMIN_CTX_FILTERS); } } @Test public void checkDefaultRedirectRule() throws Exception { try (AdminResourcesFixture testFixture = adminTestFixture()) { HttpClient client = new DefaultHttpClient(); HttpGet rootGet = new HttpGet(String.format("http://localhost:%d/", testFixture.serverPort)); HttpResponse response = client.execute(rootGet); assertEquals("admin resource root resource does not redirect to template root context.", 404, response.getStatusLine().getStatusCode()); } } @Test public void testEphemeralAdminResourcePort() throws Exception { try (AdminResourcesFixture testFixture = adminTestFixture()) { Assert.assertEquals(0, ConfigurationManager.getConfigInstance().getInt(AdminConfigImpl.CONTAINER_LISTEN_PORT)); Assert.assertTrue(testFixture.serverPort > 0); Assert.assertEquals(testFixture.serverPort, testFixture.container.getServerPort()); } } @Test public void testServiceDisabledFlag() throws Exception { disableAdminConsole(); try (AdminResourcesFixture testFixture = adminTestFixture()) { assertEquals("admin resource did not get disabled with a config flag", 0, testFixture.serverPort); } enableAdminConsole(); } @Test public void checkCustomRedirectRule() throws Exception { try (AdminResourcesFixture testFixture = adminTestFixture()) { HttpClient client = new DefaultHttpClient(); HttpGet rootGet = new HttpGet(String.format("http://localhost:%d/", testFixture.serverPort)); HttpResponse response = client.execute(rootGet); assertEquals("admin resource did not execute custom redirect routing", 404, response.getStatusLine().getStatusCode()); consumeResponse(response); HttpGet healthGet = new HttpGet(String.format("http://localhost:%d/check-me", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource did not pick a custom redirect routing", 200, response.getStatusLine().getStatusCode()); BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); assertEquals("ping resource did not return pong", br.readLine(), "pong"); healthGet = new HttpGet( String.format("http://localhost:%d/proxy-ping/or-not?when=some-day", testFixture.serverPort)); response = client.execute(healthGet); assertEquals("admin resource did not pick a custom redirect routing", 200, response.getStatusLine().getStatusCode()); br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); assertEquals("ping resource did not return pong", br.readLine(), "pong"); } } private void consumeResponse(HttpResponse response) throws IOException { if (response.getEntity() != null && response.getEntity().getContent() != null) { final BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); while (br.readLine() != null) ; } } }