/* * Copyright © 2015 Cask Data, 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 co.cask.cdap.gateway.router; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.common.conf.Constants; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteStreams; import org.apache.twill.discovery.DiscoveryService; import org.apache.twill.discovery.InMemoryDiscoveryService; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TemporaryFolder; import org.junit.rules.TestRule; import java.net.HttpURLConnection; import java.net.URL; import java.util.Collections; import java.util.Map; /** * Verify the ordering of events in the RouterPipeline. */ public class NettyRouterPipelineAuthTest { private static final String HOSTNAME = "127.0.0.1"; private static final String GATEWAY_NAME = Constants.Router.GATEWAY_DISCOVERY_NAME; private static final String SERVICE_NAME = Constants.Service.APP_FABRIC_HTTP; private static final DiscoveryService DISCOVERY_SERVICE = new InMemoryDiscoveryService(); public static final RouterResource ROUTER = new RouterResource(HOSTNAME, DISCOVERY_SERVICE, ImmutableMap.of( Constants.Security.ENABLED, "true", Constants.Security.Router.BYPASS_AUTHENTICATION_REGEX, "(/v1/repeat/.*|/v1/echo/dontfail)" )); public static final ServerResource GATEWAY_SERVER = new ServerResource(HOSTNAME, DISCOVERY_SERVICE, SERVICE_NAME); @ClassRule public static final TemporaryFolder TMP_FOLDER = new TemporaryFolder(); @SuppressWarnings("UnusedDeclaration") @ClassRule public static TestRule chain = RuleChain.outerRule(ROUTER).around(GATEWAY_SERVER); @Test public void testRouterAuthBypass() throws Exception { // mock token validator passes for no token and any token other than "Bearer failme" testGet(200, "hello", "/v1/echo/hello"); testGet(200, "hello", "/v1/echo/hello", ImmutableMap.of("Authorization", "Bearer x")); // so this should fail testGet(401, null, "/v1/echo/hello", ImmutableMap.of("Authorization", "Bearer failme")); // but /v1/echo/dontfail is configured to bypass auth testGet(200, "dontfail", "/v1/echo/dontfail", ImmutableMap.of("Authorization", "Bearer failme")); // it only bypasses on exact match, not prefix match testGet(401, null, "/v1/echo/dontfailme", ImmutableMap.of("Authorization", "Bearer failme")); // /v1/repeat is configured to bypass auth validation, on prefix match testGet(200, "hello", "/v1/repeat/hello"); testGet(200, "hello", "/v1/repeat/hello", ImmutableMap.of("Authorization", "Bearer x")); testGet(200, "hello", "/v1/repeat/hello", ImmutableMap.of("Authorization", "Bearer failme")); // even with a token that fails validation, we get the correct status code 404 testGet(404, null, "/v1/repeat/dontfail/me", ImmutableMap.of("Authorization", "Bearer failme")); } private void testGet(int expectedStatus, String expectedResponse, String path) throws Exception { testGet(expectedStatus, expectedResponse, path, Collections.<String, String>emptyMap()); } private void testGet(int expectedStatus, String expectedResponse, String path, Map<String, String> headers) throws Exception { URL url = new URL("http", HOSTNAME, ROUTER.getServiceMap().get(GATEWAY_NAME), path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setDoInput(true); for (Map.Entry<String, String> header : headers.entrySet()) { connection.setRequestProperty(header.getKey(), header.getValue()); } connection.connect(); try { Assert.assertEquals(expectedStatus, connection.getResponseCode()); if (expectedResponse != null) { byte[] content = ByteStreams.toByteArray(connection.getInputStream()); Assert.assertEquals(expectedResponse, Bytes.toString(content)); } } finally { connection.disconnect(); } } }