blob: 25a504f3a0a2ff523ccfd423b290cdb365fc75bb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.knox.gateway.hadoopauth.filter;
import static org.easymock.EasyMock.anyString;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.captureInt;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createMockBuilder;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.knox.gateway.GatewayFilter;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter;
import org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter;
import org.apache.knox.gateway.provider.federation.jwt.filter.SignatureVerificationCache;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.topology.Topology;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import javax.security.auth.Subject;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class HadoopAuthFilterTest {
private static final String SERVICE_URL = "https://localhost:8888/gateway/sandbox";
private static final String JWKS_PATH = "/knoxtoken/api/v1/jwks.json";
@Test
public void testHadoopAuthFilterAliasesOnTopologyLevel() throws Exception {
testHadoopAuthFilterAliases(true);
}
private void testHadoopAuthFilterAliases(boolean topologyLevel) throws Exception {
String aliasKey = "signature.secret";
String aliasConfigKey = "${ALIAS=" + aliasKey + "}";
String aliasValue = "password";
String clusterName = "Sample";
Topology topology = new Topology();
topology.setName(clusterName);
AliasService as = createMock(AliasService.class);
if (topologyLevel) {
expect(as.getPasswordFromAliasForCluster(clusterName, aliasKey)).andReturn(aliasValue.toCharArray()).anyTimes();
} else {
expect(as.getPasswordFromAliasForCluster(clusterName, aliasKey)).andReturn(null).anyTimes();
expect(as.getPasswordFromAliasForGateway(aliasKey)).andReturn(aliasValue.toCharArray()).anyTimes();
}
String configPrefix = "hadoop.auth.config.";
Map<String, String> props = new HashMap<>();
props.put("clusterName", clusterName);
props.put(configPrefix + "signature.secret", aliasConfigKey);
props.put(configPrefix + "test", "abc");
FilterConfig filterConfig = createMock(FilterConfig.class);
expect(filterConfig.getInitParameter(anyString()))
.andAnswer(() -> props.get(getCurrentArguments()[0].toString()))
.atLeastOnce();
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(props.keySet())).atLeastOnce();
replay(filterConfig, as);
HadoopAuthFilter hadoopAuthFilter = new HadoopAuthFilter();
Properties configuration = hadoopAuthFilter.getConfiguration(as, configPrefix, filterConfig);
assertEquals(aliasValue, configuration.getProperty(aliasKey));
assertEquals("abc", configuration.getProperty("test"));
verify(filterConfig, as);
}
@Test
public void testHadoopAuthFilterAliasesOnGatewayLevel() throws Exception {
testHadoopAuthFilterAliases(false);
}
@Test
public void testHadoopAuthFilterIgnoreDoAs() throws Exception {
Topology topology = new Topology();
topology.setName("Sample");
ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
FilterConfig filterConfig = createMock(FilterConfig.class);
expect(filterConfig.getInitParameter("config.prefix"))
.andReturn("some.prefix")
.atLeastOnce();
expect(filterConfig.getInitParameterNames())
.andReturn(Collections.enumeration(Collections.singleton(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)))
.atLeastOnce();
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS))
.andReturn("Knox, hdfs,TesT") // Spacing and case set on purpose
.atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(null).anyTimes();
Properties configProperties = createMock(Properties.class);
expect(configProperties.getProperty("signature.secret.file")).andReturn("signature.secret.file").atLeastOnce();
expect(configProperties.getProperty(anyString(), anyString())).andAnswer(() -> {
Object[] args = getCurrentArguments();
if ("type".equals(args[0])) {
return "simple"; // This is "simple", rather than "kerberos" to avoid the super class' init logic
} else {
return (String) args[1];
}
}).atLeastOnce();
HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class)
.addMockedMethod("getConfiguration", String.class, FilterConfig.class)
.withConstructor()
.createMock();
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig)))
.andReturn(configProperties)
.atLeastOnce();
replay(filterConfig, configProperties, hadoopAuthFilter, servletContext);
hadoopAuthFilter.init(filterConfig);
assertTrue(hadoopAuthFilter.ignoreDoAs("knox"));
assertTrue(hadoopAuthFilter.ignoreDoAs("hdfs"));
assertTrue(hadoopAuthFilter.ignoreDoAs("test"));
assertTrue(hadoopAuthFilter.ignoreDoAs("TEST"));
assertTrue(hadoopAuthFilter.ignoreDoAs(null));
assertTrue(hadoopAuthFilter.ignoreDoAs(""));
assertFalse(hadoopAuthFilter.ignoreDoAs("hive"));
assertFalse(hadoopAuthFilter.ignoreDoAs("HivE"));
verify(filterConfig, configProperties, hadoopAuthFilter, servletContext);
}
@Test
public void shouldNotUseJwtFilterIfProviderParamIsNotSet() throws Exception {
testIfJwtSupported(null);
}
@Test
public void shouldNotUseJwtFilterIfProviderParamIsFalse() throws Exception {
testIfJwtSupported("false");
}
@Test
public void shouldUseJwtFilterIfProviderParamIsTrue() throws Exception {
testIfJwtSupported("true");
}
@Test
public void testUnauthenticatedList() throws Exception {
HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(null).anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
EasyMock.expect(request.getPathInfo()).andReturn(JWKS_PATH).anyTimes();
EasyMock.expect(request.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request, response);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request, response, chain);
Assert.assertTrue("doFilterCalled should be true.", chain.doFilterCalled );
/* make sure the principal is anonymous */
Assert.assertEquals("anonymous", chain.subject.getPrincipals().stream().findFirst().get().getName());
}
/**
* Test to check if this can be used to bypass authentication
* @throws Exception
*/
@Test
public void testNegativeUnauthenticatedListSemicolon() throws Exception {
final String request_semicolon_path = "/knoxtoken/api/v1/jwks.json;favicon.ico";
final Capture<Integer> capturedError = EasyMock.newCapture();
final Capture<String> capturedErrorMessage = EasyMock.newCapture();
HttpServletRequest request_semicolon = EasyMock.createNiceMock(HttpServletRequest.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
/* update the default list to use favicon.ico */
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(request_semicolon_path).anyTimes();
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
/* capture errors */
response.sendError(captureInt(capturedError), capture(capturedErrorMessage));
expectLastCall().anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
replay(response);
EasyMock.expect(request_semicolon.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL+request_semicolon_path)).anyTimes();
/* try attaching favicon.ico in path */
EasyMock.expect(request_semicolon.getPathInfo()).andReturn("/knoxtoken/api/v1/token;favicon.ico").anyTimes();
EasyMock.expect(request_semicolon.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request_semicolon);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request_semicolon, response, chain);
Assert.assertFalse("doFilterCalled should be false.", chain.doFilterCalled );
/* make sure we get 403 */
Assert.assertEquals(403, capturedError.getValue().intValue());
Assert.assertEquals("Authentication required", capturedErrorMessage.getValue());
}
/**
* Test to check if this can be used to bypass authentication
* @throws Exception
*/
@Test
public void testNegativeUnauthenticatedListQuery() throws Exception {
final String request_semicolon_path = "/knoxtoken/api/v1/jwks.json?favicon.ico";
final Capture<Integer> capturedError = EasyMock.newCapture();
final Capture<String> capturedErrorMessage = EasyMock.newCapture();
HttpServletRequest request_query = EasyMock.createNiceMock(HttpServletRequest.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
/* update the default list to use favicon.ico */
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(request_semicolon_path).anyTimes();
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
/* capture errors */
response.sendError(captureInt(capturedError), capture(capturedErrorMessage));
expectLastCall().anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
replay(response);
EasyMock.expect(request_query.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL+request_semicolon_path)).anyTimes();
/* try attaching favicon.ico in path */
EasyMock.expect(request_query.getPathInfo()).andReturn("/knoxtoken/api/v1/token;favicon.ico").anyTimes();
EasyMock.expect(request_query.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request_query);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request_query, response, chain);
Assert.assertFalse("doFilterCalled should be false.", chain.doFilterCalled );
/* make sure we get 403 */
Assert.assertEquals(403, capturedError.getValue().intValue());
Assert.assertEquals("Authentication required", capturedErrorMessage.getValue());
}
/**
* Test to check if this can be used to bypass authentication
* @throws Exception
*/
@Test
public void testNegativeUnauthenticatedListAmpersand() throws Exception {
final String request_semicolon_path = "/knoxtoken/api/v1/jwks.json&favicon.ico";
final Capture<Integer> capturedError = EasyMock.newCapture();
final Capture<String> capturedErrorMessage = EasyMock.newCapture();
HttpServletRequest request_ampersand = EasyMock.createNiceMock(HttpServletRequest.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
/* update the default list to use favicon.ico */
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(request_semicolon_path).anyTimes();
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
/* capture errors */
response.sendError(captureInt(capturedError), capture(capturedErrorMessage));
expectLastCall().anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
replay(response);
EasyMock.expect(request_ampersand.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL+request_semicolon_path)).anyTimes();
/* try attaching favicon.ico in path */
EasyMock.expect(request_ampersand.getPathInfo()).andReturn("/knoxtoken/api/v1/token;favicon.ico").anyTimes();
EasyMock.expect(request_ampersand.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request_ampersand);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request_ampersand, response, chain);
Assert.assertFalse("doFilterCalled should be false.", chain.doFilterCalled );
/* make sure we get 403 */
Assert.assertEquals(403, capturedError.getValue().intValue());
Assert.assertEquals("Authentication required", capturedErrorMessage.getValue());
}
/**
* Test to check if this can be used to bypass authentication
* @throws Exception
*/
@Test
public void testNegativeUnauthenticatedListDash() throws Exception {
final String request_semicolon_path = "/knoxtoken/api/v1/jwks.json-favicon.ico";
final Capture<Integer> capturedError = EasyMock.newCapture();
final Capture<String> capturedErrorMessage = EasyMock.newCapture();
HttpServletRequest request_dash = EasyMock.createNiceMock(HttpServletRequest.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
/* update the default list to use favicon.ico */
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(request_semicolon_path).anyTimes();
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
/* capture errors */
response.sendError(captureInt(capturedError), capture(capturedErrorMessage));
expectLastCall().anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
replay(response);
EasyMock.expect(request_dash.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL+request_semicolon_path)).anyTimes();
/* try attaching favicon.ico in path */
EasyMock.expect(request_dash.getPathInfo()).andReturn("/knoxtoken/api/v1/token;favicon.ico").anyTimes();
EasyMock.expect(request_dash.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request_dash);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request_dash, response, chain);
Assert.assertFalse("doFilterCalled should be false.", chain.doFilterCalled );
/* make sure we get 403 */
Assert.assertEquals(403, capturedError.getValue().intValue());
Assert.assertEquals("Authentication required", capturedErrorMessage.getValue());
}
/**
* Test to check if this can be used to bypass authentication
* @throws Exception
*/
@Test
public void testNegativeUnauthenticatedListSpace() throws Exception {
final String request_semicolon_path = "/knoxtoken/api/v1/jwks.json favicon.ico";
final Capture<Integer> capturedError = EasyMock.newCapture();
final Capture<String> capturedErrorMessage = EasyMock.newCapture();
HttpServletRequest request_space = EasyMock.createNiceMock(HttpServletRequest.class);
GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn("false").anyTimes();
/* update the default list to use favicon.ico */
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(request_semicolon_path).anyTimes();
HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
/* capture errors */
response.sendError(captureInt(capturedError), capture(capturedErrorMessage));
expectLastCall().anyTimes();
EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(SERVICE_URL);
EasyMock.expect(response.getOutputStream()).andAnswer(
DummyServletOutputStream::new).anyTimes();
replay(response);
EasyMock.expect(request_space.getRequestURL()).andReturn(new StringBuffer(SERVICE_URL+request_semicolon_path)).anyTimes();
/* try attaching favicon.ico in path */
EasyMock.expect(request_space.getPathInfo()).andReturn("/knoxtoken/api/v1/token;favicon.ico").anyTimes();
EasyMock.expect(request_space.getQueryString()).andReturn(null);
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter, request_space);
hadoopAuthFilter.init(filterConfig);
DummyFilterChain chain = new DummyFilterChain();
hadoopAuthFilter.doFilter(request_space, response, chain);
Assert.assertFalse("doFilterCalled should be false.", chain.doFilterCalled );
/* make sure we get 403 */
Assert.assertEquals(403, capturedError.getValue().intValue());
Assert.assertEquals("Authentication required", capturedErrorMessage.getValue());
}
public static class DummyFilterChain implements FilterChain {
boolean doFilterCalled;
Subject subject;
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException {
doFilterCalled = true;
subject = Subject.getSubject( AccessController.getContext() );
}
}
static class DummyServletOutputStream extends ServletOutputStream {
@Override
public void write(int b) {
}
@Override
public void setWriteListener(WriteListener arg0) {
}
@Override
public boolean isReady() {
return false;
}
}
private HadoopAuthFilter testIfJwtSupported(String supportJwt) throws Exception {
final GatewayFilter.Holder filterConfig = createMock(GatewayFilter.Holder.class);
expect(filterConfig.getInitParameterNames()).andReturn(Collections.enumeration(Collections.emptyList()));
expect(filterConfig.getInitParameter(GatewayConfig.PROXYUSER_SERVICES_IGNORE_DOAS)).andReturn("service").atLeastOnce();
expect(filterConfig.getInitParameter("config.prefix")).andReturn("some.prefix").atLeastOnce();
expect(filterConfig.getInitParameter("support.jwt")).andReturn(supportJwt).anyTimes();
expect(filterConfig.getInitParameter("hadoop.auth.unauthenticated.path.list")).andReturn(null).anyTimes();
final boolean isJwtSupported = Boolean.parseBoolean(supportJwt);
if (isJwtSupported) {
expect(filterConfig.getInitParameter(JWTFederationFilter.KNOX_TOKEN_AUDIENCES)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.KNOX_TOKEN_QUERY_PARAM_NAME)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.JWKS_URL)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.TOKEN_PRINCIPAL_CLAIM)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.TOKEN_VERIFICATION_PEM)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.JWT_UNAUTHENTICATED_PATHS_PARAM)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(AbstractJWTFilter.JWT_EXPECTED_ISSUER)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(AbstractJWTFilter.JWT_EXPECTED_SIGALG)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(JWTFederationFilter.ALLOWED_JWS_TYPES)).andReturn(null).anyTimes();
expect(filterConfig.getInitParameter(SignatureVerificationCache.TOKENS_VERIFIED_CACHE_MAX)).andReturn(null).anyTimes();
}
final ServletContext servletContext = createMock(ServletContext.class);
expect(servletContext.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE)).andReturn("test").anyTimes();
expect(servletContext.getAttribute("signer.secret.provider.object")).andReturn(null).atLeastOnce();
if (isJwtSupported) {
expect(servletContext.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(null).anyTimes();
}
expect(filterConfig.getServletContext()).andReturn(servletContext).atLeastOnce();
final HadoopAuthFilter hadoopAuthFilter = createMockBuilder(HadoopAuthFilter.class).addMockedMethod("getConfiguration", String.class, FilterConfig.class).withConstructor()
.createMock();
final Properties config = new Properties();
config.put("type", "simple");
expect(hadoopAuthFilter.getConfiguration(eq("some.prefix."), eq(filterConfig))).andReturn(config).atLeastOnce();
replay(servletContext, filterConfig, hadoopAuthFilter);
hadoopAuthFilter.init(filterConfig);
assertEquals(isJwtSupported, hadoopAuthFilter.isJwtSupported());
return hadoopAuthFilter;
}
}