You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by wh...@apache.org on 2014/03/05 02:48:42 UTC
svn commit: r1574283 - in /hadoop/common/trunk/hadoop-common-project:
hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/
hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/
hadoop-common/ hadoop-common/s...
Author: wheat9
Date: Wed Mar 5 01:48:42 2014
New Revision: 1574283
URL: http://svn.apache.org/r1574283
Log:
HADOOP-10379. Protect authentication cookies with the HttpOnly and Secure flags. Contributed by Haohui Mai.
Added:
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
Modified:
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java?rev=1574283&r1=1574282&r2=1574283&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java Wed Mar 5 01:48:42 2014
@@ -13,6 +13,8 @@
*/
package org.apache.hadoop.security.authentication.server;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.util.Signer;
@@ -32,9 +34,8 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.Random;
+import java.text.SimpleDateFormat;
+import java.util.*;
/**
* The {@link AuthenticationFilter} enables protecting web application resources with different (pluggable)
@@ -69,6 +70,9 @@ import java.util.Random;
* the prefix from it and it will pass them to the the authentication handler for initialization. Properties that do
* not start with the prefix will not be passed to the authentication handler initialization.
*/
+
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
public class AuthenticationFilter implements Filter {
private static Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);
@@ -331,6 +335,7 @@ public class AuthenticationFilter implem
String unauthorizedMsg = "";
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
+ boolean isHttps = "https".equals(httpRequest.getScheme());
try {
boolean newToken = false;
AuthenticationToken token;
@@ -378,8 +383,8 @@ public class AuthenticationFilter implem
};
if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) {
String signedToken = signer.sign(token.toString());
- Cookie cookie = createCookie(signedToken);
- httpResponse.addCookie(cookie);
+ createAuthCookie(httpResponse, signedToken, getCookieDomain(),
+ getCookiePath(), token.getExpires(), isHttps);
}
filterChain.doFilter(httpRequest, httpResponse);
}
@@ -392,31 +397,52 @@ public class AuthenticationFilter implem
}
if (unauthorizedResponse) {
if (!httpResponse.isCommitted()) {
- Cookie cookie = createCookie("");
- cookie.setMaxAge(0);
- httpResponse.addCookie(cookie);
- httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, unauthorizedMsg);
+ createAuthCookie(httpResponse, "", getCookieDomain(),
+ getCookiePath(), 0, isHttps);
+ httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+ unauthorizedMsg);
}
}
}
/**
- * Creates the Hadoop authentiation HTTP cookie.
- * <p/>
- * It sets the domain and path specified in the configuration.
+ * Creates the Hadoop authentication HTTP cookie.
*
* @param token authentication token for the cookie.
+ * @param expires UNIX timestamp that indicates the expire date of the
+ * cookie. It has no effect if its value < 0.
*
- * @return the HTTP cookie.
+ * XXX the following code duplicate some logic in Jetty / Servlet API,
+ * because of the fact that Hadoop is stuck at servlet 3.0 and jetty 6
+ * right now.
*/
- protected Cookie createCookie(String token) {
- Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, token);
- if (getCookieDomain() != null) {
- cookie.setDomain(getCookieDomain());
+ public static void createAuthCookie(HttpServletResponse resp, String token,
+ String domain, String path, long expires,
+ boolean isSecure) {
+ StringBuilder sb = new StringBuilder(AuthenticatedURL.AUTH_COOKIE).append
+ ("=").append(token);
+
+ if (path != null) {
+ sb.append("; Path=").append(path);
}
- if (getCookiePath() != null) {
- cookie.setPath(getCookiePath());
+
+ if (domain != null) {
+ sb.append("; Domain=").append(domain);
}
- return cookie;
+
+ if (expires >= 0) {
+ Date date = new Date(expires);
+ SimpleDateFormat df = new SimpleDateFormat("EEE, " +
+ "dd-MMM-yyyy HH:mm:ss zzz");
+ df.setTimeZone(TimeZone.getTimeZone("GMT"));
+ sb.append("; Expires=").append(df.format(date));
+ }
+
+ if (isSecure) {
+ sb.append("; Secure");
+ }
+
+ sb.append("; HttpOnly");
+ resp.addHeader("Set-Cookie", sb.toString());
}
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java?rev=1574283&r1=1574282&r2=1574283&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java Wed Mar 5 01:48:42 2014
@@ -18,6 +18,7 @@ import org.apache.hadoop.security.authen
import org.apache.hadoop.security.authentication.util.Signer;
import org.junit.Assert;
import org.junit.Test;
+import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -31,9 +32,7 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.Properties;
-import java.util.Vector;
+import java.util.*;
public class TestAuthenticationFilter {
@@ -400,103 +399,87 @@ public class TestAuthenticationFilter {
boolean invalidToken,
boolean expired) throws Exception {
AuthenticationFilter filter = new AuthenticationFilter();
- try {
- FilterConfig config = Mockito.mock(FilterConfig.class);
- Mockito.when(config.getInitParameter("management.operation.return")).
- thenReturn("true");
- Mockito.when(config.getInitParameter("expired.token")).
- thenReturn(Boolean.toString(expired));
- Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE)).thenReturn(
- DummyAuthenticationHandler.class.getName());
- Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TOKEN_VALIDITY)).thenReturn("1000");
- Mockito.when(config.getInitParameter(AuthenticationFilter.SIGNATURE_SECRET)).thenReturn("secret");
- Mockito.when(config.getInitParameterNames()).thenReturn(
- new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
- AuthenticationFilter.AUTH_TOKEN_VALIDITY,
- AuthenticationFilter.SIGNATURE_SECRET,
- "management.operation.return",
- "expired.token")).elements());
-
- if (withDomainPath) {
- Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_DOMAIN)).thenReturn(".foo.com");
- Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_PATH)).thenReturn("/bar");
- Mockito.when(config.getInitParameterNames()).thenReturn(
- new Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
- AuthenticationFilter.AUTH_TOKEN_VALIDITY,
- AuthenticationFilter.SIGNATURE_SECRET,
- AuthenticationFilter.COOKIE_DOMAIN,
- AuthenticationFilter.COOKIE_PATH,
- "management.operation.return")).elements());
+ FilterConfig config = Mockito.mock(FilterConfig.class);
+ Mockito.when(config.getInitParameter("management.operation.return")).
+ thenReturn("true");
+ Mockito.when(config.getInitParameter("expired.token")).
+ thenReturn(Boolean.toString(expired));
+ Mockito.when(config.getInitParameter(AuthenticationFilter.AUTH_TYPE))
+ .thenReturn(DummyAuthenticationHandler.class.getName());
+ Mockito.when(config.getInitParameter(AuthenticationFilter
+ .AUTH_TOKEN_VALIDITY)).thenReturn("1000");
+ Mockito.when(config.getInitParameter(AuthenticationFilter
+ .SIGNATURE_SECRET)).thenReturn("secret");
+ Mockito.when(config.getInitParameterNames()).thenReturn(new
+ Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
+ AuthenticationFilter.AUTH_TOKEN_VALIDITY,
+ AuthenticationFilter.SIGNATURE_SECRET, "management.operation" +
+ ".return", "expired.token")).elements());
+
+ if (withDomainPath) {
+ Mockito.when(config.getInitParameter(AuthenticationFilter
+ .COOKIE_DOMAIN)).thenReturn(".foo.com");
+ Mockito.when(config.getInitParameter(AuthenticationFilter.COOKIE_PATH))
+ .thenReturn("/bar");
+ Mockito.when(config.getInitParameterNames()).thenReturn(new
+ Vector<String>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
+ AuthenticationFilter.AUTH_TOKEN_VALIDITY,
+ AuthenticationFilter.SIGNATURE_SECRET,
+ AuthenticationFilter.COOKIE_DOMAIN, AuthenticationFilter
+ .COOKIE_PATH, "management.operation.return")).elements());
+ }
+
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ Mockito.when(request.getParameter("authenticated")).thenReturn("true");
+ Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer
+ ("http://foo:8080/bar"));
+ Mockito.when(request.getQueryString()).thenReturn("authenticated=true");
+
+ if (invalidToken) {
+ Mockito.when(request.getCookies()).thenReturn(new Cookie[]{new Cookie
+ (AuthenticatedURL.AUTH_COOKIE, "foo")});
+ }
+
+ HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+ FilterChain chain = Mockito.mock(FilterChain.class);
+
+ final HashMap<String, String> cookieMap = new HashMap<String, String>();
+ Mockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ String cookieHeader = (String)invocation.getArguments()[1];
+ parseCookieMap(cookieHeader, cookieMap);
+ return null;
}
+ }).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
+ try {
filter.init(config);
-
- HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
- Mockito.when(request.getParameter("authenticated")).thenReturn("true");
- Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer("http://foo:8080/bar"));
- Mockito.when(request.getQueryString()).thenReturn("authenticated=true");
-
- if (invalidToken) {
- Mockito.when(request.getCookies()).thenReturn(
- new Cookie[] { new Cookie(AuthenticatedURL.AUTH_COOKIE, "foo")}
- );
- }
-
- HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
-
- FilterChain chain = Mockito.mock(FilterChain.class);
-
- final boolean[] calledDoFilter = new boolean[1];
-
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- calledDoFilter[0] = true;
- return null;
- }
- }
- ).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
-
- final Cookie[] setCookie = new Cookie[1];
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] args = invocation.getArguments();
- setCookie[0] = (Cookie) args[0];
- return null;
- }
- }
- ).when(response).addCookie(Mockito.<Cookie>anyObject());
-
filter.doFilter(request, response, chain);
if (expired) {
Mockito.verify(response, Mockito.never()).
addCookie(Mockito.any(Cookie.class));
} else {
- Assert.assertNotNull(setCookie[0]);
- Assert.assertEquals(AuthenticatedURL.AUTH_COOKIE, setCookie[0].getName());
- Assert.assertTrue(setCookie[0].getValue().contains("u="));
- Assert.assertTrue(setCookie[0].getValue().contains("p="));
- Assert.assertTrue(setCookie[0].getValue().contains("t="));
- Assert.assertTrue(setCookie[0].getValue().contains("e="));
- Assert.assertTrue(setCookie[0].getValue().contains("s="));
- Assert.assertTrue(calledDoFilter[0]);
+ String v = cookieMap.get(AuthenticatedURL.AUTH_COOKIE);
+ Assert.assertNotNull(v);
+ Assert.assertTrue(v.contains("u=") && v.contains("p=") && v.contains
+ ("t=") && v.contains("e=") && v.contains("s="));
+ Mockito.verify(chain).doFilter(Mockito.any(ServletRequest.class),
+ Mockito.any(ServletResponse.class));
Signer signer = new Signer("secret".getBytes());
- String value = signer.verifyAndExtract(setCookie[0].getValue());
+ String value = signer.verifyAndExtract(v);
AuthenticationToken token = AuthenticationToken.parse(value);
Assert.assertEquals(System.currentTimeMillis() + 1000 * 1000,
token.getExpires(), 100);
if (withDomainPath) {
- Assert.assertEquals(".foo.com", setCookie[0].getDomain());
- Assert.assertEquals("/bar", setCookie[0].getPath());
+ Assert.assertEquals(".foo.com", cookieMap.get("Domain"));
+ Assert.assertEquals("/bar", cookieMap.get("Path"));
} else {
- Assert.assertNull(setCookie[0].getDomain());
- Assert.assertNull(setCookie[0].getPath());
+ Assert.assertFalse(cookieMap.containsKey("Domain"));
+ Assert.assertFalse(cookieMap.containsKey("Path"));
}
}
} finally {
@@ -504,6 +487,26 @@ public class TestAuthenticationFilter {
}
}
+ private static void parseCookieMap(String cookieHeader, HashMap<String,
+ String> cookieMap) {
+ for (String pair : cookieHeader.split(";")) {
+ String p = pair.trim();
+ int idx = p.indexOf('=');
+ final String k, v;
+ if (idx == -1) {
+ k = p;
+ v = null;
+ } else if (idx == p.length()) {
+ k = p.substring(0, idx - 1);
+ v = null;
+ } else {
+ k = p.substring(0, idx);
+ v = p.substring(idx + 1);
+ }
+ cookieMap.put(k, v);
+ }
+ }
+
@Test
public void testDoFilterAuthentication() throws Exception {
_testDoFilterAuthentication(false, false, false);
@@ -601,41 +604,39 @@ public class TestAuthenticationFilter {
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
-
FilterChain chain = Mockito.mock(FilterChain.class);
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Assert.fail();
- return null;
- }
- }
- ).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
+ verifyUnauthorized(filter, request, response, chain);
+ } finally {
+ filter.destroy();
+ }
+ }
- final Cookie[] setCookie = new Cookie[1];
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] args = invocation.getArguments();
- setCookie[0] = (Cookie) args[0];
- return null;
- }
- }
- ).when(response).addCookie(Mockito.<Cookie>anyObject());
+ private static void verifyUnauthorized(AuthenticationFilter filter,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ FilterChain chain) throws
+ IOException,
+ ServletException {
+ final HashMap<String, String> cookieMap = new HashMap<String, String>();
+ Mockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ String cookieHeader = (String) invocation.getArguments()[1];
+ parseCookieMap(cookieHeader, cookieMap);
+ return null;
+ }
+ }).when(response).addHeader(Mockito.eq("Set-Cookie"), Mockito.anyString());
- filter.doFilter(request, response, chain);
+ filter.doFilter(request, response, chain);
- Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.anyString());
+ Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse
+ .SC_UNAUTHORIZED), Mockito.anyString());
+ Mockito.verify(chain, Mockito.never()).doFilter(Mockito.any
+ (ServletRequest.class), Mockito.any(ServletResponse.class));
- Assert.assertNotNull(setCookie[0]);
- Assert.assertEquals(AuthenticatedURL.AUTH_COOKIE, setCookie[0].getName());
- Assert.assertEquals("", setCookie[0].getValue());
- } finally {
- filter.destroy();
- }
+ Assert.assertTrue(cookieMap.containsKey(AuthenticatedURL.AUTH_COOKIE));
+ Assert.assertEquals("", cookieMap.get(AuthenticatedURL.AUTH_COOKIE));
}
@Test
@@ -665,38 +666,9 @@ public class TestAuthenticationFilter {
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
-
FilterChain chain = Mockito.mock(FilterChain.class);
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Assert.fail();
- return null;
- }
- }
- ).when(chain).doFilter(Mockito.<ServletRequest>anyObject(), Mockito.<ServletResponse>anyObject());
-
- final Cookie[] setCookie = new Cookie[1];
- Mockito.doAnswer(
- new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] args = invocation.getArguments();
- setCookie[0] = (Cookie) args[0];
- return null;
- }
- }
- ).when(response).addCookie(Mockito.<Cookie>anyObject());
-
- filter.doFilter(request, response, chain);
-
- Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.anyString());
-
- Assert.assertNotNull(setCookie[0]);
- Assert.assertEquals(AuthenticatedURL.AUTH_COOKIE, setCookie[0].getName());
- Assert.assertEquals("", setCookie[0].getValue());
+ verifyUnauthorized(filter, request, response, chain);
} finally {
filter.destroy();
}
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1574283&r1=1574282&r2=1574283&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Wed Mar 5 01:48:42 2014
@@ -361,6 +361,9 @@ Release 2.4.0 - UNRELEASED
HADOOP-8691. FsShell can print "Found xxx items" unnecessarily often.
(Daryn Sharp via wheat9)
+ HADOOP-10379. Protect authentication cookies with the HttpOnly and Secure
+ flags. (wheat9)
+
OPTIMIZATIONS
BUG FIXES
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java?rev=1574283&r1=1574282&r2=1574283&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java Wed Mar 5 01:48:42 2014
@@ -67,12 +67,14 @@ import org.mortbay.jetty.Handler;
import org.mortbay.jetty.MimeTypes;
import org.mortbay.jetty.RequestLog;
import org.mortbay.jetty.Server;
+import org.mortbay.jetty.SessionManager;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.handler.HandlerCollection;
import org.mortbay.jetty.handler.RequestLogHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.SslSocketConnector;
+import org.mortbay.jetty.servlet.AbstractSessionManager;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.DefaultServlet;
import org.mortbay.jetty.servlet.FilterHolder;
@@ -356,6 +358,13 @@ public final class HttpServer2 implement
threadPool.setDaemon(true);
webServer.setThreadPool(threadPool);
+ SessionManager sm = webAppContext.getSessionHandler().getSessionManager();
+ if (sm instanceof AbstractSessionManager) {
+ AbstractSessionManager asm = (AbstractSessionManager)sm;
+ asm.setHttpOnly(true);
+ asm.setSecureCookies(true);
+ }
+
ContextHandlerCollection contexts = new ContextHandlerCollection();
RequestLog requestLog = HttpRequestLog.getRequestLog(name);
Added: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java?rev=1574283&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java (added)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpCookieFlag.java Wed Mar 5 01:48:42 2014
@@ -0,0 +1,141 @@
+/**
+ * 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.http;
+
+import junit.framework.Assert;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileUtil;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
+import org.apache.hadoop.security.ssl.SSLFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.servlet.*;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+
+public class TestHttpCookieFlag {
+ private static final String BASEDIR = System.getProperty("test.build.dir",
+ "target/test-dir") + "/" + TestHttpCookieFlag.class.getSimpleName();
+ private static String keystoresDir;
+ private static String sslConfDir;
+ private static SSLFactory clientSslFactory;
+ private static HttpServer2 server;
+
+ public static class DummyAuthenticationFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException,
+ ServletException {
+ HttpServletResponse resp = (HttpServletResponse) response;
+ boolean isHttps = "https".equals(request.getScheme());
+ AuthenticationFilter.createAuthCookie(resp, "token", null, null, -1,
+ isHttps);
+ chain.doFilter(request, resp);
+ }
+
+ @Override
+ public void destroy() {
+ }
+ }
+ public static class DummyFilterInitializer extends FilterInitializer {
+ @Override
+ public void initFilter(FilterContainer container, Configuration conf) {
+ container.addFilter("DummyAuth", DummyAuthenticationFilter.class
+ .getName(), null);
+ }
+ }
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ Configuration conf = new Configuration();
+ conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY,
+ DummyFilterInitializer.class.getName());
+
+ File base = new File(BASEDIR);
+ FileUtil.fullyDelete(base);
+ base.mkdirs();
+ keystoresDir = new File(BASEDIR).getAbsolutePath();
+ sslConfDir = KeyStoreTestUtil.getClasspathDir(TestSSLHttpServer.class);
+
+ KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, conf, false);
+ Configuration sslConf = new Configuration(false);
+ sslConf.addResource("ssl-server.xml");
+ sslConf.addResource("ssl-client.xml");
+
+ clientSslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, sslConf);
+ clientSslFactory.init();
+
+ server = new HttpServer2.Builder()
+ .setName("test")
+ .addEndpoint(new URI("http://localhost"))
+ .addEndpoint(new URI("https://localhost"))
+ .setConf(conf)
+ .keyPassword(sslConf.get("ssl.server.keystore.keypassword"))
+ .keyStore(sslConf.get("ssl.server.keystore.location"),
+ sslConf.get("ssl.server.keystore.password"),
+ sslConf.get("ssl.server.keystore.type", "jks"))
+ .trustStore(sslConf.get("ssl.server.truststore.location"),
+ sslConf.get("ssl.server.truststore.password"),
+ sslConf.get("ssl.server.truststore.type", "jks")).build();
+ server.addServlet("echo", "/echo", TestHttpServer.EchoServlet.class);
+ server.start();
+ }
+
+ @Test
+ public void testHttpCookie() throws IOException {
+ URL base = new URL("http://" + NetUtils.getHostPortString(server
+ .getConnectorAddress(0)));
+ HttpURLConnection conn = (HttpURLConnection) new URL(base,
+ "/echo").openConnection();
+ Assert.assertEquals(AuthenticatedURL.AUTH_COOKIE + "=token; " +
+ "HttpOnly", conn.getHeaderField("Set-Cookie"));
+ }
+
+ @Test
+ public void testHttpsCookie() throws IOException, GeneralSecurityException {
+ URL base = new URL("https://" + NetUtils.getHostPortString(server
+ .getConnectorAddress(1)));
+ HttpsURLConnection conn = (HttpsURLConnection) new URL(base,
+ "/echo").openConnection();
+ conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory());
+ Assert.assertEquals(AuthenticatedURL.AUTH_COOKIE + "=token; " +
+ "Secure; HttpOnly", conn.getHeaderField("Set-Cookie"));
+ }
+
+ @AfterClass
+ public static void cleanup() throws Exception {
+ server.stop();
+ FileUtil.fullyDelete(new File(BASEDIR));
+ KeyStoreTestUtil.cleanupSSLConfig(keystoresDir, sslConfDir);
+ clientSslFactory.destroy();
+ }
+}