/** * 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.hadoop.fs.http.server; import junit.framework.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.http.client.HttpFSFileSystem; import org.apache.hadoop.fs.http.client.HttpFSKerberosAuthenticator; import org.apache.hadoop.fs.http.client.HttpFSKerberosAuthenticator.DelegationTokenOperation; import org.apache.hadoop.lib.service.DelegationTokenIdentifier; import org.apache.hadoop.lib.service.DelegationTokenManager; import org.apache.hadoop.lib.service.DelegationTokenManagerException; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.server.AuthenticationHandler; import org.apache.hadoop.security.authentication.server.AuthenticationToken; import org.apache.hadoop.security.token.Token; import org.apache.hadoop.test.HFSTestCase; import org.apache.hadoop.test.TestDir; import org.apache.hadoop.test.TestDirHelper; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.junit.Test; import org.mockito.Mockito; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.MediaType; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetAddress; import java.net.InetSocketAddress; public class TestHttpFSKerberosAuthenticationHandler extends HFSTestCase { @Test @TestDir public void testManagementOperations() throws Exception { String dir = TestDirHelper.getTestDir().getAbsolutePath(); Configuration httpfsConf = new Configuration(false); HttpFSServerWebApp server = new HttpFSServerWebApp(dir, dir, dir, dir, httpfsConf); server.setAuthority(new InetSocketAddress(InetAddress.getLocalHost(), 14000)); AuthenticationHandler handler = new HttpFSKerberosAuthenticationHandlerForTesting(); try { server.init(); handler.init(null); testNonManagementOperation(handler); testManagementOperationErrors(handler); testGetToken(handler, null); testGetToken(handler, "foo"); testCancelToken(handler); testRenewToken(handler); } finally { if (handler != null) { handler.destroy(); } server.destroy(); } } private void testNonManagementOperation(AuthenticationHandler handler) throws Exception { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(null); Assert.assertTrue(handler.managementOperation(null, request, null)); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(HttpFSFileSystem.Operation.CREATE.toString()); Assert.assertTrue(handler.managementOperation(null, request, null)); } private void testManagementOperationErrors(AuthenticationHandler handler) throws Exception { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(DelegationTokenOperation.GETDELEGATIONTOKEN.toString()); Mockito.when(request.getMethod()).thenReturn("FOO"); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_BAD_REQUEST), Mockito.startsWith("Wrong HTTP method")); Mockito.reset(response); Mockito.when(request.getMethod()). thenReturn(DelegationTokenOperation.GETDELEGATIONTOKEN.getHttpMethod()); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.contains("requires SPNEGO")); } private void testGetToken(AuthenticationHandler handler, String renewer) throws Exception { DelegationTokenOperation op = DelegationTokenOperation.GETDELEGATIONTOKEN; HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(op.toString()); Mockito.when(request.getMethod()). thenReturn(op.getHttpMethod()); AuthenticationToken token = Mockito.mock(AuthenticationToken.class); Mockito.when(token.getUserName()).thenReturn("user"); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.when(request.getParameter(HttpFSKerberosAuthenticator.RENEWER_PARAM)). thenReturn(renewer); Mockito.reset(response); StringWriter writer = new StringWriter(); PrintWriter pwriter = new PrintWriter(writer); Mockito.when(response.getWriter()).thenReturn(pwriter); Assert.assertFalse(handler.managementOperation(token, request, response)); if (renewer == null) { Mockito.verify(token).getUserName(); } else { Mockito.verify(token, Mockito.never()).getUserName(); } Mockito.verify(response).setStatus(HttpServletResponse.SC_OK); Mockito.verify(response).setContentType(MediaType.APPLICATION_JSON); pwriter.close(); String responseOutput = writer.toString(); String tokenLabel = HttpFSKerberosAuthenticator.DELEGATION_TOKEN_JSON; Assert.assertTrue(responseOutput.contains(tokenLabel)); Assert.assertTrue(responseOutput.contains( HttpFSKerberosAuthenticator.DELEGATION_TOKEN_URL_STRING_JSON)); JSONObject json = (JSONObject) new JSONParser().parse(responseOutput); json = (JSONObject) json.get(tokenLabel); String tokenStr; tokenStr = (String) json.get(HttpFSKerberosAuthenticator.DELEGATION_TOKEN_URL_STRING_JSON); Token<DelegationTokenIdentifier> dt = new Token<DelegationTokenIdentifier>(); dt.decodeFromUrlString(tokenStr); HttpFSServerWebApp.get().get(DelegationTokenManager.class).verifyToken(dt); } private void testCancelToken(AuthenticationHandler handler) throws Exception { DelegationTokenOperation op = DelegationTokenOperation.CANCELDELEGATIONTOKEN; HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(op.toString()); Mockito.when(request.getMethod()). thenReturn(op.getHttpMethod()); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_BAD_REQUEST), Mockito.contains("requires the parameter [token]")); Mockito.reset(response); Token<DelegationTokenIdentifier> token = HttpFSServerWebApp.get().get(DelegationTokenManager.class).createToken( UserGroupInformation.getCurrentUser(), "foo"); Mockito.when(request.getParameter(HttpFSKerberosAuthenticator.TOKEN_PARAM)). thenReturn(token.encodeToUrlString()); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.verify(response).setStatus(HttpServletResponse.SC_OK); try { HttpFSServerWebApp.get().get(DelegationTokenManager.class).verifyToken(token); Assert.fail(); } catch (DelegationTokenManagerException ex) { Assert.assertTrue(ex.toString().contains("DT01")); } } private void testRenewToken(AuthenticationHandler handler) throws Exception { DelegationTokenOperation op = DelegationTokenOperation.RENEWDELEGATIONTOKEN; HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Mockito.when(request.getParameter(HttpFSFileSystem.OP_PARAM)). thenReturn(op.toString()); Mockito.when(request.getMethod()). thenReturn(op.getHttpMethod()); Assert.assertFalse(handler.managementOperation(null, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.contains("equires SPNEGO authentication established")); Mockito.reset(response); AuthenticationToken token = Mockito.mock(AuthenticationToken.class); Mockito.when(token.getUserName()).thenReturn("user"); Assert.assertFalse(handler.managementOperation(token, request, response)); Mockito.verify(response).sendError( Mockito.eq(HttpServletResponse.SC_BAD_REQUEST), Mockito.contains("requires the parameter [token]")); Mockito.reset(response); StringWriter writer = new StringWriter(); PrintWriter pwriter = new PrintWriter(writer); Mockito.when(response.getWriter()).thenReturn(pwriter); Token<DelegationTokenIdentifier> dToken = HttpFSServerWebApp.get().get(DelegationTokenManager.class).createToken( UserGroupInformation.getCurrentUser(), "user"); Mockito.when(request.getParameter(HttpFSKerberosAuthenticator.TOKEN_PARAM)). thenReturn(dToken.encodeToUrlString()); Assert.assertFalse(handler.managementOperation(token, request, response)); Mockito.verify(response).setStatus(HttpServletResponse.SC_OK); pwriter.close(); Assert.assertTrue(writer.toString().contains("long")); HttpFSServerWebApp.get().get(DelegationTokenManager.class).verifyToken(dToken); } @Test @TestDir public void testAuthenticate() throws Exception { String dir = TestDirHelper.getTestDir().getAbsolutePath(); Configuration httpfsConf = new Configuration(false); HttpFSServerWebApp server = new HttpFSServerWebApp(dir, dir, dir, dir, httpfsConf); server.setAuthority(new InetSocketAddress(InetAddress.getLocalHost(), 14000)); AuthenticationHandler handler = new HttpFSKerberosAuthenticationHandlerForTesting(); try { server.init(); handler.init(null); testValidDelegationToken(handler); testInvalidDelegationToken(handler); } finally { if (handler != null) { handler.destroy(); } server.destroy(); } } private void testValidDelegationToken(AuthenticationHandler handler) throws Exception { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Token<DelegationTokenIdentifier> dToken = HttpFSServerWebApp.get().get(DelegationTokenManager.class).createToken( UserGroupInformation.getCurrentUser(), "user"); Mockito.when(request.getParameter(HttpFSKerberosAuthenticator.DELEGATION_PARAM)). thenReturn(dToken.encodeToUrlString()); AuthenticationToken token = handler.authenticate(request, response); Assert.assertEquals(UserGroupInformation.getCurrentUser().getShortUserName(), token.getUserName()); Assert.assertEquals(0, token.getExpires()); Assert.assertEquals(HttpFSKerberosAuthenticationHandler.TYPE, token.getType()); Assert.assertTrue(token.isExpired()); } private void testInvalidDelegationToken(AuthenticationHandler handler) throws Exception { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); HttpServletResponse response = Mockito.mock(HttpServletResponse.class); Mockito.when(request.getParameter(HttpFSKerberosAuthenticator.DELEGATION_PARAM)). thenReturn("invalid"); try { handler.authenticate(request, response); Assert.fail(); } catch (AuthenticationException ex) { //NOP } catch (Exception ex) { Assert.fail(); } } }