diff --git hadoop-common-project/hadoop-auth/pom.xml hadoop-common-project/hadoop-auth/pom.xml
index 5fcb938..a501799 100644
--- hadoop-common-project/hadoop-auth/pom.xml
+++ hadoop-common-project/hadoop-auth/pom.xml
@@ -139,6 +139,17 @@
true
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
index 91dc26c..c2a94ea 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
@@ -194,6 +194,21 @@
+ org.apache.hadoop
+ hadoop-minikdc
+ test
+
+
+
+ org.apache.hadoop
+ hadoop-auth
+ test
+ test-jar
+ ${project.version}
+
+
+
+
com.sun.jersey.jersey-test-framework
jersey-test-framework-grizzly2
test
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
index 2c2a7aa..1f1ce9b 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
@@ -22,6 +22,7 @@
import java.lang.reflect.UndeclaredThrowableException;
import java.security.AccessControlException;
import java.nio.ByteBuffer;
+import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Collection;
@@ -36,6 +37,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -57,6 +59,8 @@
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
@@ -67,6 +71,13 @@
import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationResponse;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationResponse;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenResponse;
+import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenResponse;
+import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenResponse;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
@@ -85,6 +96,7 @@
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
+import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants;
import org.apache.hadoop.yarn.server.resourcemanager.RMServerUtils;
@@ -109,6 +121,7 @@
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterMetricsInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CredentialsInfo;
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.DelegationToken;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FairSchedulerInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FifoSchedulerInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.LocalResourceInfo;
@@ -118,6 +131,7 @@
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerTypeInfo;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.StatisticsItemInfo;
+import org.apache.hadoop.yarn.server.utils.BuilderUtils;
import org.apache.hadoop.yarn.util.ConverterUtils;
import org.apache.hadoop.yarn.webapp.BadRequestException;
import org.apache.hadoop.yarn.webapp.NotFoundException;
@@ -139,6 +153,9 @@
private final Configuration conf;
private @Context HttpServletResponse response;
+ public final static String DELEGATION_TOKEN_HEADER =
+ "Hadoop-YARN-RM-Delegation-Token";
+
@Inject
public RMWebServices(final ResourceManager rm, Configuration conf) {
this.rm = rm;
@@ -772,8 +789,18 @@ private RMApp getRMAppForAppId(String appId) {
private UserGroupInformation getCallerUserGroupInformation(
HttpServletRequest hsr) {
+ return getCallerUserGroupInformation(hsr, false);
+ }
+
+ private UserGroupInformation getCallerUserGroupInformation(
+ HttpServletRequest hsr, boolean usePrincipal) {
String remoteUser = hsr.getRemoteUser();
+ if (usePrincipal) {
+ Principal princ = hsr.getUserPrincipal();
+ remoteUser = princ == null ? null : princ.getName();
+ }
+
UserGroupInformation callerUGI = null;
if (remoteUser != null) {
callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
@@ -887,8 +914,8 @@ private NewApplication createNewApplication() {
throw new YarnRuntimeException(msg, e);
}
NewApplication appId =
- new NewApplication(resp.getApplicationId().toString(), new ResourceInfo(
- resp.getMaximumResourceCapability()));
+ new NewApplication(resp.getApplicationId().toString(),
+ new ResourceInfo(resp.getMaximumResourceCapability()));
return appId;
}
@@ -962,7 +989,8 @@ protected Resource createAppSubmissionContextResource(
* @throws IOException
*/
protected ContainerLaunchContext createContainerLaunchContext(
- ApplicationSubmissionContextInfo newApp) throws BadRequestException, IOException {
+ ApplicationSubmissionContextInfo newApp) throws BadRequestException,
+ IOException {
// create container launch context
@@ -1033,4 +1061,218 @@ private Credentials createCredentials(CredentialsInfo credentials) {
}
return ret;
}
+
+ private UserGroupInformation createKerberosUserGroupInformation(
+ HttpServletRequest hsr) throws AuthorizationException, YarnException {
+
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
+ if (callerUGI == null) {
+ String msg = "Unable to obtain user name, user not authenticated";
+ throw new AuthorizationException(msg);
+ }
+
+ String authType = hsr.getAuthType();
+ if (!KerberosAuthenticationHandler.TYPE.equals(authType)) {
+ String msg =
+ "Delegation token operations can only be carried out on a "
+ + "Kerberos authenticated channel";
+ throw new YarnException(msg);
+ }
+
+ callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
+ return callerUGI;
+ }
+
+ @POST
+ @Path("/delegation-token")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response postDelegationToken(DelegationToken tokenData,
+ @Context HttpServletRequest hsr) throws AuthorizationException,
+ IOException, InterruptedException, Exception {
+
+ init();
+ UserGroupInformation callerUGI;
+ try {
+ callerUGI = createKerberosUserGroupInformation(hsr);
+ } catch (YarnException ye) {
+ return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build();
+ }
+ if (tokenData.getToken() == null || tokenData.getToken().isEmpty()) {
+ return createDelegationToken(tokenData, hsr, callerUGI);
+ }
+
+ return renewDelegationToken(tokenData, hsr, callerUGI);
+ }
+
+ private Response createDelegationToken(DelegationToken tokenData,
+ HttpServletRequest hsr, UserGroupInformation callerUGI)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+ if (tokenData.getRenewer() == null || tokenData.getRenewer().isEmpty()) {
+ throw new BadRequestException(
+ "Renewer must be specified in the request body");
+ }
+ final String renewer = tokenData.getRenewer();
+ GetDelegationTokenResponse resp;
+ try {
+ resp =
+ callerUGI
+ .doAs(new PrivilegedExceptionAction() {
+ @Override
+ public GetDelegationTokenResponse run() throws IOException,
+ YarnException {
+ GetDelegationTokenRequest createReq =
+ GetDelegationTokenRequest.newInstance(renewer);
+ return rm.getClientRMService().getDelegationToken(createReq);
+ }
+ });
+ } catch (Exception e) {
+ LOG.info("Create delegation token request failed", e);
+ throw e;
+ }
+
+ Token tk =
+ new Token(resp.getRMDelegationToken()
+ .getIdentifier().array(), resp.getRMDelegationToken().getPassword()
+ .array(), new Text(resp.getRMDelegationToken().getKind()), new Text(
+ resp.getRMDelegationToken().getService()));
+ DelegationToken respToken = new DelegationToken();
+ respToken.setToken(tk.encodeToUrlString());
+ return Response.status(Status.OK).entity(respToken).build();
+ }
+
+ private Response renewDelegationToken(DelegationToken tokenData,
+ HttpServletRequest hsr, UserGroupInformation callerUGI)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ Token token =
+ extractToken(tokenData.getToken());
+
+ org.apache.hadoop.yarn.api.records.Token dToken =
+ BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind()
+ .toString(), token.getPassword(), token.getService().toString());
+ final RenewDelegationTokenRequest req =
+ RenewDelegationTokenRequest.newInstance(dToken);
+
+ RenewDelegationTokenResponse resp;
+ try {
+ resp =
+ callerUGI
+ .doAs(new PrivilegedExceptionAction() {
+ @Override
+ public RenewDelegationTokenResponse run() throws IOException,
+ YarnException {
+ return rm.getClientRMService().renewDelegationToken(req);
+ }
+ });
+ } catch (UndeclaredThrowableException ue) {
+ if (ue.getCause() instanceof YarnException) {
+ if (ue.getCause().getCause() instanceof InvalidToken) {
+ throw new BadRequestException(ue.getCause().getCause().getMessage());
+ } else if (ue.getCause().getCause() instanceof org.apache.hadoop.security.AccessControlException) {
+ return Response.status(Status.FORBIDDEN)
+ .entity(ue.getCause().getCause().getMessage()).build();
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ } catch (Exception e) {
+ LOG.info("Renew delegation token request failed", e);
+ throw e;
+ }
+ long renewTime = resp.getNextExpirationTime();
+
+ DelegationToken respToken = new DelegationToken();
+ respToken.setNextExpirationTime(renewTime);
+
+ return Response.status(Status.OK).entity(respToken).build();
+ }
+
+ // For cancelling tokens, the encoded token is passed as a header
+ // There are two reasons for this -
+ // 1. Passing a request body as part of a DELETE request is not
+ // allowed by Jetty
+ // 2. Passing the encoded token as part of the url is not ideal
+ // since urls tend to get logged and anyone with access to
+ // the logs can extract tokens which are meant to be secret
+ @DELETE
+ @Path("/delegation-token")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response cancelDelegationToken(@Context HttpServletRequest hsr)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ init();
+ UserGroupInformation callerUGI;
+ try {
+ callerUGI = createKerberosUserGroupInformation(hsr);
+ } catch (YarnException ye) {
+ return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build();
+ }
+
+ Token token = extractToken(hsr);
+
+ org.apache.hadoop.yarn.api.records.Token dToken =
+ BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind()
+ .toString(), token.getPassword(), token.getService().toString());
+ final CancelDelegationTokenRequest req =
+ CancelDelegationTokenRequest.newInstance(dToken);
+
+ try {
+ callerUGI
+ .doAs(new PrivilegedExceptionAction() {
+ @Override
+ public CancelDelegationTokenResponse run() throws IOException,
+ YarnException {
+ return rm.getClientRMService().cancelDelegationToken(req);
+ }
+ });
+ } catch (UndeclaredThrowableException ue) {
+ if (ue.getCause() instanceof YarnException) {
+ if (ue.getCause().getCause() instanceof InvalidToken) {
+ throw new BadRequestException(ue.getCause().getCause().getMessage());
+ } else if (ue.getCause().getCause() instanceof org.apache.hadoop.security.AccessControlException) {
+ return Response.status(Status.FORBIDDEN)
+ .entity(ue.getCause().getCause().getMessage()).build();
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ } catch (Exception e) {
+ LOG.info("Renew delegation token request failed", e);
+ throw e;
+ }
+
+ return Response.status(Status.OK).build();
+ }
+
+ private Token extractToken(
+ HttpServletRequest request) {
+ String encodedToken = request.getHeader(DELEGATION_TOKEN_HEADER);
+ if (encodedToken == null) {
+ String msg =
+ "Header '" + DELEGATION_TOKEN_HEADER
+ + "' containing encoded token not found";
+ throw new BadRequestException(msg);
+ }
+ return extractToken(encodedToken);
+ }
+
+ private Token extractToken(String encodedToken) {
+ Token token =
+ new Token();
+ try {
+ token.decodeFromUrlString(encodedToken);
+ } catch (Exception ie) {
+ String msg = "Could not decode encoded token";
+ throw new BadRequestException(msg);
+ }
+ return token;
+ }
}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/DelegationToken.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/DelegationToken.java
new file mode 100644
index 0000000..ea89bc4
--- /dev/null
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/DelegationToken.java
@@ -0,0 +1,62 @@
+/**
+ * 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.yarn.server.resourcemanager.webapp.dao;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "delegation-token")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class DelegationToken {
+
+ String token;
+ String renewer;
+ @XmlElement(name = "next-expiration-time")
+ Long nextExpirationTime;
+
+ public DelegationToken() {
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public String getRenewer() {
+ return renewer;
+ }
+
+ public Long getNextExpirationTime() {
+ return nextExpirationTime;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public void setRenewer(String renewer) {
+ this.renewer = renewer;
+ }
+
+ public void setNextExpirationTime(long nextExpirationTime) {
+ this.nextExpirationTime = Long.valueOf(nextExpirationTime);
+ }
+
+}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokens.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokens.java
new file mode 100644
index 0000000..66cecc1
--- /dev/null
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokens.java
@@ -0,0 +1,769 @@
+/**
+ * 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.yarn.server.resourcemanager.webapp;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.ws.rs.core.MediaType;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
+import org.apache.hadoop.minikdc.MiniKdc;
+import org.apache.hadoop.security.authentication.KerberosTestUtils;
+import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
+import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.util.Time;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
+import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
+import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
+import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
+import org.apache.hadoop.yarn.server.resourcemanager.security.QueueACLsManager;
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.DelegationToken;
+import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
+import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
+import org.apache.hadoop.yarn.webapp.WebServicesTestUtils;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+@RunWith(Parameterized.class)
+public class TestRMWebServicesDelegationTokens extends JerseyTest {
+
+ private static final File testRootDir = new File("target",
+ TestRMWebServicesDelegationTokens.class.getName() + "-root");
+ private static File httpSpnegoKeytabFile = new File(
+ KerberosTestUtils.getKeytabFile());
+
+ private static String httpSpnegoPrincipal = KerberosTestUtils
+ .getServerPrincipal();
+
+ private static boolean miniKDCStarted = false;
+ private static MiniKdc testMiniKDC;
+ static {
+ try {
+ testMiniKDC = new MiniKdc(MiniKdc.createConf(), testRootDir);
+ } catch (Exception e) {
+ assertTrue("Couldn't create MiniKDC", false);
+ }
+ }
+
+ private static MockRM rm;
+
+ private Injector injector;
+
+ private boolean isKerberosAuth = false;
+
+ @Singleton
+ public static class TestKerberosAuthFilter extends AuthenticationFilter {
+ @Override
+ protected Properties getConfiguration(String configPrefix,
+ FilterConfig filterConfig) throws ServletException {
+
+ Properties properties =
+ super.getConfiguration(configPrefix, filterConfig);
+
+ properties.put(KerberosAuthenticationHandler.PRINCIPAL,
+ httpSpnegoPrincipal);
+ properties.put(KerberosAuthenticationHandler.KEYTAB,
+ httpSpnegoKeytabFile.getAbsolutePath());
+ properties.put(AuthenticationFilter.AUTH_TYPE, "kerberos");
+ return properties;
+ }
+ }
+
+ @Singleton
+ public static class TestSimpleAuthFilter extends AuthenticationFilter {
+ @Override
+ protected Properties getConfiguration(String configPrefix,
+ FilterConfig filterConfig) throws ServletException {
+
+ Properties properties =
+ super.getConfiguration(configPrefix, filterConfig);
+
+ properties.put(KerberosAuthenticationHandler.PRINCIPAL,
+ httpSpnegoPrincipal);
+ properties.put(KerberosAuthenticationHandler.KEYTAB,
+ httpSpnegoKeytabFile.getAbsolutePath());
+ properties.put(AuthenticationFilter.AUTH_TYPE, "simple");
+ properties.put(PseudoAuthenticationHandler.ANONYMOUS_ALLOWED, "false");
+ return properties;
+ }
+ }
+
+ private class TestServletModule extends ServletModule {
+ public Configuration rmconf = new Configuration();
+
+ @Override
+ protected void configureServlets() {
+ bind(JAXBContextResolver.class);
+ bind(RMWebServices.class);
+ bind(GenericExceptionHandler.class);
+ Configuration rmconf = new Configuration();
+ rmconf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS,
+ YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS);
+ rmconf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class,
+ ResourceScheduler.class);
+ rmconf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true);
+ rm = new MockRM(rmconf);
+ bind(ResourceManager.class).toInstance(rm);
+ bind(RMContext.class).toInstance(rm.getRMContext());
+ bind(ApplicationACLsManager.class).toInstance(
+ rm.getApplicationACLsManager());
+ bind(QueueACLsManager.class).toInstance(rm.getQueueACLsManager());
+ if (isKerberosAuth == true) {
+ filter("/*").through(TestKerberosAuthFilter.class);
+ } else {
+ filter("/*").through(TestSimpleAuthFilter.class);
+ }
+ serve("/*").with(GuiceContainer.class);
+ }
+ }
+
+ private Injector getSimpleAuthInjector() {
+ return Guice.createInjector(new TestServletModule() {
+ @Override
+ protected void configureServlets() {
+ isKerberosAuth = false;
+ rmconf.set(
+ CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+ "simple");
+ super.configureServlets();
+ }
+ });
+ }
+
+ private Injector getKerberosAuthInjector() {
+ return Guice.createInjector(new TestServletModule() {
+ @Override
+ protected void configureServlets() {
+ isKerberosAuth = true;
+ rmconf.set(
+ CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+ "kerberos");
+ rmconf.set(YarnConfiguration.RM_WEBAPP_SPNEGO_USER_NAME_KEY,
+ httpSpnegoPrincipal);
+ rmconf.set(YarnConfiguration.RM_WEBAPP_SPNEGO_KEYTAB_FILE_KEY,
+ httpSpnegoKeytabFile.getAbsolutePath());
+ rmconf.set(YarnConfiguration.NM_WEBAPP_SPNEGO_USER_NAME_KEY,
+ httpSpnegoPrincipal);
+ rmconf.set(YarnConfiguration.NM_WEBAPP_SPNEGO_KEYTAB_FILE_KEY,
+ httpSpnegoKeytabFile.getAbsolutePath());
+
+ super.configureServlets();
+ }
+ });
+ }
+
+ public class GuiceServletConfig extends GuiceServletContextListener {
+
+ @Override
+ protected Injector getInjector() {
+ return injector;
+ }
+ }
+
+ @Parameters
+ public static Collection