001/** 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. See accompanying LICENSE file. 013 */ 014package org.apache.hadoop.hbase.http; 015 016import java.util.List; 017import java.io.File; 018import java.io.IOException; 019import java.net.HttpURLConnection; 020import java.net.HttpCookie; 021import java.net.URI; 022import java.net.URL; 023import javax.net.ssl.HttpsURLConnection; 024import javax.servlet.Filter; 025import javax.servlet.FilterConfig; 026import javax.servlet.FilterChain; 027import javax.servlet.ServletRequest; 028import javax.servlet.ServletResponse; 029import javax.servlet.ServletException; 030import javax.servlet.http.HttpServletResponse; 031import java.security.GeneralSecurityException; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.apache.hadoop.conf.Configuration; 036import org.apache.hadoop.fs.FileUtil; 037import org.apache.hadoop.net.NetUtils; 038import org.apache.hadoop.security.authentication.server.AuthenticationFilter; 039import org.apache.hadoop.security.ssl.KeyStoreTestUtil; 040import org.apache.hadoop.security.ssl.SSLFactory; 041 042import org.junit.Assert; 043import org.junit.AfterClass; 044import org.junit.BeforeClass; 045import org.junit.ClassRule; 046import org.junit.Test; 047import org.junit.experimental.categories.Category; 048 049@Category({ MiscTests.class, SmallTests.class}) 050public class TestHttpCookieFlag { 051 @ClassRule 052 public static final HBaseClassTestRule CLASS_RULE = 053 HBaseClassTestRule.forClass(TestHttpCookieFlag.class); 054 055 private static final String BASEDIR = System.getProperty("test.build.dir", 056 "target/test-dir") + "/" + 057 org.apache.hadoop.hbase.http.TestHttpCookieFlag.class.getSimpleName(); 058 private static String keystoresDir; 059 private static String sslConfDir; 060 private static SSLFactory clientSslFactory; 061 private static HttpServer server; 062 063 public static class DummyAuthenticationFilter implements Filter { 064 065 @Override 066 public void init(FilterConfig filterConfig) throws ServletException { 067 } 068 069 @Override 070 public void doFilter(ServletRequest request, ServletResponse response, 071 FilterChain chain) throws IOException, 072 ServletException { 073 HttpServletResponse resp = (HttpServletResponse) response; 074 boolean isHttps = "https".equals(request.getScheme()); 075 AuthenticationFilter.createAuthCookie(resp, "token", null, null, -1, 076 true, isHttps); 077 chain.doFilter(request, resp); 078 } 079 080 @Override 081 public void destroy() { 082 } 083 } 084 public static class DummyFilterInitializer extends FilterInitializer { 085 @Override 086 public void initFilter(FilterContainer container, Configuration conf) { 087 container.addFilter("DummyAuth", DummyAuthenticationFilter.class 088 .getName(), null); 089 } 090 } 091 092 @BeforeClass 093 public static void setUp() throws Exception { 094 Configuration conf = new Configuration(); 095 conf.set(HttpServer.FILTER_INITIALIZERS_PROPERTY, 096 DummyFilterInitializer.class.getName()); 097 conf.setInt("hbase.http.max.threads", 19); /* acceptors=2 + selectors=16 + request=1 */ 098 System.setProperty("hadoop.log.dir", BASEDIR); /* needed for /logs */ 099 100 File base = new File(BASEDIR); 101 FileUtil.fullyDelete(base); 102 base.mkdirs(); 103 keystoresDir = new File(BASEDIR).getAbsolutePath(); 104 sslConfDir = KeyStoreTestUtil.getClasspathDir(TestSSLHttpServer.class); 105 106 KeyStoreTestUtil.setupSSLConfig(keystoresDir, sslConfDir, conf, false); 107 Configuration sslConf = KeyStoreTestUtil.getSslConfig(); 108 109 clientSslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, sslConf); 110 clientSslFactory.init(); 111 112 server = new HttpServer.Builder() 113 .setName("test") 114 .addEndpoint(new URI("http://localhost")) 115 .addEndpoint(new URI("https://localhost")) 116 .setConf(conf) 117 .keyPassword(sslConf.get("ssl.server.keystore.keypassword")) 118 .keyStore(sslConf.get("ssl.server.keystore.location"), 119 sslConf.get("ssl.server.keystore.password"), 120 sslConf.get("ssl.server.keystore.type", "jks")) 121 .trustStore(sslConf.get("ssl.server.truststore.location"), 122 sslConf.get("ssl.server.truststore.password"), 123 sslConf.get("ssl.server.truststore.type", "jks")) 124 .build(); 125 server.addPrivilegedServlet("echo", "/echo", TestHttpServer.EchoServlet.class); 126 server.start(); 127 } 128 129 @Test 130 public void testHttpCookie() throws IOException { 131 URL base = new URL("http://" + NetUtils.getHostPortString(server 132 .getConnectorAddress(0))); 133 HttpURLConnection conn = (HttpURLConnection) new URL(base, 134 "/echo").openConnection(); 135 136 String header = conn.getHeaderField("Set-Cookie"); 137 Assert.assertTrue(header != null); 138 List<HttpCookie> cookies = HttpCookie.parse(header); 139 Assert.assertTrue(!cookies.isEmpty()); 140 Assert.assertTrue(header.contains("; HttpOnly")); 141 Assert.assertTrue("token".equals(cookies.get(0).getValue())); 142 } 143 144 @Test 145 public void testHttpsCookie() throws IOException, GeneralSecurityException { 146 URL base = new URL("https://" + NetUtils.getHostPortString(server 147 .getConnectorAddress(1))); 148 HttpsURLConnection conn = (HttpsURLConnection) new URL(base, 149 "/echo").openConnection(); 150 conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory()); 151 152 String header = conn.getHeaderField("Set-Cookie"); 153 Assert.assertTrue(header != null); 154 155 List<HttpCookie> cookies = HttpCookie.parse(header); 156 Assert.assertTrue(!cookies.isEmpty()); 157 Assert.assertTrue(header.contains("; HttpOnly")); 158 Assert.assertTrue(cookies.get(0).getSecure()); 159 Assert.assertTrue("token".equals(cookies.get(0).getValue())); 160 } 161 162 @Test 163 public void testHttpsCookieDefaultServlets() throws Exception { 164 HttpsURLConnection conn = null; 165 166 URL base = new URL("https://" + NetUtils.getHostPortString(server 167 .getConnectorAddress(1)) + "/"); 168 169 for (String servlet : new String[] { "static", "stacks", "logLevel", "jmx", "logs" }) { 170 conn = (HttpsURLConnection) new URL(base, 171 "/" + servlet).openConnection(); 172 conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory()); 173 174 String header = conn.getHeaderField("Set-Cookie"); 175 Assert.assertTrue(header != null); 176 List<HttpCookie> cookies = HttpCookie.parse(header); 177 Assert.assertTrue(!cookies.isEmpty()); 178 Assert.assertTrue(header.contains("; HttpOnly")); 179 Assert.assertTrue(cookies.get(0).getSecure()); 180 Assert.assertTrue("token".equals(cookies.get(0).getValue())); 181 } 182 } 183 184 @AfterClass 185 public static void cleanup() throws Exception { 186 server.stop(); 187 FileUtil.fullyDelete(new File(BASEDIR)); 188 KeyStoreTestUtil.cleanupSSLConfig(keystoresDir, sslConfDir); 189 clientSslFactory.destroy(); 190 } 191}