diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineAuthenticator.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineAuthenticator.java
deleted file mode 100644
index bd05f4a..0000000
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineAuthenticator.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * 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.client.api.impl;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.hadoop.classification.InterfaceAudience.Private;
-import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
-import org.apache.hadoop.security.authentication.client.AuthenticationException;
-import org.apache.hadoop.security.authentication.client.Authenticator;
-import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
-import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
-import org.apache.hadoop.security.token.Token;
-import org.apache.hadoop.yarn.api.records.timeline.TimelineDelegationTokenResponse;
-import org.apache.hadoop.yarn.security.client.TimelineAuthenticationConsts;
-import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
-import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenOperation;
-import org.apache.hadoop.yarn.webapp.YarnJacksonJaxbJsonProvider;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/**
- * A KerberosAuthenticator subclass that fallback to
- * {@link TimelineAuthenticationConsts}.
- */
-@Private
-@Unstable
-public class TimelineAuthenticator extends KerberosAuthenticator {
-
- private static ObjectMapper mapper;
- private static TimelineAuthenticator authenticator;
- private static ConnectionConfigurator connConfigurator;
-
- static {
- mapper = new ObjectMapper();
- YarnJacksonJaxbJsonProvider.configObjectMapper(mapper);
- authenticator = new TimelineAuthenticator();
- }
-
- /**
- * Returns the fallback authenticator if the server does not use Kerberos
- * SPNEGO HTTP authentication.
- *
- * @return a {@link TimelineAuthenticationConsts} instance.
- */
- @Override
- protected Authenticator getFallBackAuthenticator() {
- return new TimelineAuthenticator();
- }
-
- public static void injectDelegationToken(Map params,
- Token> dtToken)
- throws IOException {
- if (dtToken != null) {
- params.put(TimelineAuthenticationConsts.DELEGATION_PARAM,
- dtToken.encodeToUrlString());
- }
- }
-
- @Private
- @VisibleForTesting
- boolean hasDelegationToken(URL url) {
- if (url.getQuery() == null) {
- return false;
- } else {
- return url.getQuery().contains(
- TimelineAuthenticationConsts.DELEGATION_PARAM + "=");
- }
- }
-
- @Override
- public void authenticate(URL url, AuthenticatedURL.Token token)
- throws IOException, AuthenticationException {
- if (!hasDelegationToken(url)) {
- super.authenticate(url, token);
- }
- }
-
- public static void setStaticConnectionConfigurator(
- ConnectionConfigurator connConfigurator) {
- TimelineAuthenticator.connConfigurator = connConfigurator;
- }
-
- public static Token getDelegationToken(
- URL url, AuthenticatedURL.Token token, String renewer) throws IOException {
- TimelineDelegationTokenOperation op =
- TimelineDelegationTokenOperation.GETDELEGATIONTOKEN;
- Map params = new HashMap();
- params.put(TimelineAuthenticationConsts.OP_PARAM, op.toString());
- params.put(TimelineAuthenticationConsts.RENEWER_PARAM, renewer);
- url = appendParams(url, params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(authenticator, connConfigurator);
- try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(op.getHttpMethod());
- TimelineDelegationTokenResponse dtRes = validateAndParseResponse(conn);
- if (!dtRes.getType().equals(
- TimelineAuthenticationConsts.DELEGATION_TOKEN_URL)) {
- throw new IOException("The response content is not expected: "
- + dtRes.getContent());
- }
- String tokenStr = dtRes.getContent().toString();
- Token dToken =
- new Token();
- dToken.decodeFromUrlString(tokenStr);
- return dToken;
- } catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
- }
- }
-
- public static long renewDelegationToken(URL url,
- AuthenticatedURL.Token token,
- Token dToken) throws IOException {
- Map params = new HashMap();
- params.put(TimelineAuthenticationConsts.OP_PARAM,
- TimelineDelegationTokenOperation.RENEWDELEGATIONTOKEN.toString());
- params.put(TimelineAuthenticationConsts.TOKEN_PARAM,
- dToken.encodeToUrlString());
- url = appendParams(url, params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(authenticator, connConfigurator);
- try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(
- TimelineDelegationTokenOperation.RENEWDELEGATIONTOKEN.getHttpMethod());
- TimelineDelegationTokenResponse dtRes = validateAndParseResponse(conn);
- if (!dtRes.getType().equals(
- TimelineAuthenticationConsts.DELEGATION_TOKEN_EXPIRATION_TIME)) {
- throw new IOException("The response content is not expected: "
- + dtRes.getContent());
- }
- return Long.valueOf(dtRes.getContent().toString());
- } catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
- }
- }
-
- public static void cancelDelegationToken(URL url,
- AuthenticatedURL.Token token,
- Token dToken) throws IOException {
- Map params = new HashMap();
- params.put(TimelineAuthenticationConsts.OP_PARAM,
- TimelineDelegationTokenOperation.CANCELDELEGATIONTOKEN.toString());
- params.put(TimelineAuthenticationConsts.TOKEN_PARAM,
- dToken.encodeToUrlString());
- url = appendParams(url, params);
- AuthenticatedURL aUrl =
- new AuthenticatedURL(authenticator, connConfigurator);
- try {
- HttpURLConnection conn = aUrl.openConnection(url, token);
- conn.setRequestMethod(TimelineDelegationTokenOperation.CANCELDELEGATIONTOKEN
- .getHttpMethod());
- validateAndParseResponse(conn);
- } catch (AuthenticationException ex) {
- throw new IOException(ex.toString(), ex);
- }
- }
-
- /**
- * Convenience method that appends parameters an HTTP URL.
- *
- * @param url
- * the url.
- * @param params
- * the query string parameters.
- *
- * @return a URL
- *
- * @throws IOException
- * thrown if an IO error occurs.
- */
- public static URL appendParams(URL url, Map params)
- throws IOException {
- StringBuilder sb = new StringBuilder();
- sb.append(url);
- String separator = url.toString().contains("?") ? "&" : "?";
- for (Map.Entry entry : params.entrySet()) {
- sb.append(separator).append(entry.getKey()).append("=").
- append(URLEncoder.encode(entry.getValue(), "UTF8"));
- separator = "&";
- }
- return new URL(sb.toString());
- }
-
- /**
- * Validates the response of an HttpURLConnection. If the current
- * status code is not 200, it will throw an exception with a detail message
- * using Server side error messages if available. Otherwise,
- * {@link TimelineDelegationTokenResponse} will be parsed and returned.
- *
- * @param conn
- * the HttpURLConnection.
- * @return
- * @throws IOException
- * thrown if the current status code is not 200 or the JSON response
- * cannot be parsed correctly
- */
- private static TimelineDelegationTokenResponse validateAndParseResponse(
- HttpURLConnection conn) throws IOException {
- int status = conn.getResponseCode();
- JsonNode json = mapper.readTree(conn.getInputStream());
- if (status == HttpURLConnection.HTTP_OK) {
- return mapper.readValue(json, TimelineDelegationTokenResponse.class);
- } else {
- // If the status code is not 200, some thing wrong should happen at the
- // server side, the JSON content is going to contain exception details.
- // We can use the JSON content to reconstruct the exception object.
- try {
- String message =
- json.get(TimelineAuthenticationConsts.ERROR_MESSAGE_JSON)
- .getTextValue();
- String exception =
- json.get(TimelineAuthenticationConsts.ERROR_EXCEPTION_JSON)
- .getTextValue();
- String className =
- json.get(TimelineAuthenticationConsts.ERROR_CLASSNAME_JSON)
- .getTextValue();
-
- try {
- ClassLoader cl = TimelineAuthenticator.class.getClassLoader();
- Class> klass = cl.loadClass(className);
- Constructor> constr = klass.getConstructor(String.class);
- throw (IOException) constr.newInstance(message);
- } catch (IOException ex) {
- throw ex;
- } catch (Exception ex) {
- throw new IOException(MessageFormat.format("{0} - {1}", exception,
- message));
- }
- } catch (IOException ex) {
- if (ex.getCause() instanceof IOException) {
- throw (IOException) ex.getCause();
- }
- throw new IOException(
- MessageFormat.format("HTTP status [{0}], {1}",
- status, conn.getResponseMessage()));
- }
- }
- }
-
-}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java
index fbddd14..c0f46a1 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java
@@ -20,14 +20,14 @@
import java.io.File;
import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.GeneralSecurityException;
+import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@@ -43,13 +43,14 @@
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
-import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
import org.apache.hadoop.security.ssl.SSLFactory;
import org.apache.hadoop.security.token.Token;
+import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticatedURL;
+import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticator;
+import org.apache.hadoop.security.token.delegation.web.KerberosDelegationTokenAuthenticator;
+import org.apache.hadoop.security.token.delegation.web.PseudoDelegationTokenAuthenticator;
import org.apache.hadoop.yarn.api.records.timeline.TimelineDomain;
import org.apache.hadoop.yarn.api.records.timeline.TimelineDomains;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEntities;
@@ -60,8 +61,6 @@
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
-import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenSelector;
-import org.apache.hadoop.yarn.util.timeline.TimelineUtils;
import org.apache.hadoop.yarn.webapp.YarnJacksonJaxbJsonProvider;
import org.codehaus.jackson.map.ObjectMapper;
@@ -81,7 +80,6 @@
private static final Log LOG = LogFactory.getLog(TimelineClientImpl.class);
private static final String RESOURCE_URI_STR = "/ws/v1/timeline/";
- private static final String URL_PARAM_USER_NAME = "user.name";
private static final Joiner JOINER = Joiner.on("");
public final static int DEFAULT_SOCKET_TIMEOUT = 1 * 60 * 1000; // 1 minute
@@ -99,9 +97,11 @@
}
private Client client;
+ private ConnectionConfigurator connConfigurator;
+ private DelegationTokenAuthenticator authenticator;
+ private DelegationTokenAuthenticatedURL.Token token;
private URI resURI;
private boolean isEnabled;
- private KerberosAuthenticatedURLConnectionFactory urlFactory;
public TimelineClientImpl() {
super(TimelineClientImpl.class.getName());
@@ -116,15 +116,17 @@ protected void serviceInit(Configuration conf) throws Exception {
} else {
ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(YarnJacksonJaxbJsonProvider.class);
- ConnectionConfigurator connConfigurator = newConnConfigurator(conf);
+ connConfigurator = newConnConfigurator(conf);
if (UserGroupInformation.isSecurityEnabled()) {
- TimelineAuthenticator.setStaticConnectionConfigurator(connConfigurator);
- urlFactory = new KerberosAuthenticatedURLConnectionFactory(connConfigurator);
- client = new Client(new URLConnectionClientHandler(urlFactory), cc);
+ authenticator = new KerberosDelegationTokenAuthenticator();
} else {
- client = new Client(new URLConnectionClientHandler(
- new PseudoAuthenticatedURLConnectionFactory(connConfigurator)), cc);
+ authenticator = new PseudoDelegationTokenAuthenticator();
}
+ authenticator.setConnectionConfigurator(connConfigurator);
+ client = new Client(new URLConnectionClientHandler(
+ new TimelineURLConnectionFactory()), cc);
+ token = new DelegationTokenAuthenticatedURL.Token();
+
if (YarnConfiguration.useHttps(conf)) {
resURI = URI
.create(JOINER.join("https://", conf.get(
@@ -137,9 +139,6 @@ protected void serviceInit(Configuration conf) throws Exception {
YarnConfiguration.DEFAULT_TIMELINE_SERVICE_WEBAPP_ADDRESS),
RESOURCE_URI_STR));
}
- if (UserGroupInformation.isSecurityEnabled()) {
- urlFactory.setService(TimelineUtils.buildTimelineTokenService(conf));
- }
LOG.info("Timeline service address: " + resURI);
}
super.serviceInit(conf);
@@ -199,11 +198,34 @@ private ClientResponse doPosting(Object obj, String path) throws IOException, Ya
return resp;
}
+ @SuppressWarnings("unchecked")
@Override
public Token getDelegationToken(
- String renewer) throws IOException, YarnException {
- return TimelineAuthenticator.getDelegationToken(resURI.toURL(),
- urlFactory.token, renewer);
+ final String renewer) throws IOException, YarnException {
+ boolean isPoxyUser =
+ UserGroupInformation.getCurrentUser().getAuthenticationMethod()
+ == UserGroupInformation.AuthenticationMethod.PROXY;
+ UserGroupInformation ugi = isPoxyUser ?
+ UserGroupInformation.getCurrentUser().getRealUser()
+ : UserGroupInformation.getCurrentUser();
+ final String doAsUser = isPoxyUser ?
+ UserGroupInformation.getCurrentUser().getShortUserName() : null;
+ try {
+ return ugi.doAs(
+ new PrivilegedExceptionAction>() {
+ @Override
+ public Token run() throws Exception {
+ DelegationTokenAuthenticatedURL authUrl =
+ new DelegationTokenAuthenticatedURL(authenticator, connConfigurator);
+ return (Token) authUrl.getDelegationToken(
+ resURI.toURL(), token, renewer, doAsUser);
+ }
+ });
+ } catch (UndeclaredThrowableException e) {
+ throw new IOException(e.getCause());
+ } catch (InterruptedException e) {
+ throw new IOException(e);
+ }
}
@Private
@@ -223,91 +245,35 @@ public ClientResponse doPostingObject(Object object, String path) {
}
}
- private static class PseudoAuthenticatedURLConnectionFactory
- implements HttpURLConnectionFactory {
-
- private ConnectionConfigurator connConfigurator;
-
- public PseudoAuthenticatedURLConnectionFactory(
- ConnectionConfigurator connConfigurator) {
- this.connConfigurator = connConfigurator;
- }
-
- @Override
- public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
- Map params = new HashMap();
- params.put(URL_PARAM_USER_NAME,
- UserGroupInformation.getCurrentUser().getShortUserName());
- url = TimelineAuthenticator.appendParams(url, params);
- if (LOG.isDebugEnabled()) {
- LOG.debug("URL with delegation token: " + url);
- }
- return connConfigurator.configure((HttpURLConnection) url.openConnection());
- }
-
- }
- private static class KerberosAuthenticatedURLConnectionFactory
+ private class TimelineURLConnectionFactory
implements HttpURLConnectionFactory {
- private AuthenticatedURL.Token token;
- private TimelineAuthenticator authenticator;
- private Token dToken;
- private Text service;
- private ConnectionConfigurator connConfigurator;
-
- public KerberosAuthenticatedURLConnectionFactory(
- ConnectionConfigurator connConfigurator) {
- token = new AuthenticatedURL.Token();
- authenticator = new TimelineAuthenticator();
- this.connConfigurator = connConfigurator;
- }
-
@Override
- public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
+ public HttpURLConnection getHttpURLConnection(final URL url) throws IOException {
+ boolean isPoxyUser =
+ UserGroupInformation.getCurrentUser().getAuthenticationMethod()
+ == UserGroupInformation.AuthenticationMethod.PROXY;
+ UserGroupInformation ugi = isPoxyUser ?
+ UserGroupInformation.getCurrentUser().getRealUser()
+ : UserGroupInformation.getCurrentUser();
+ final String doAsUser = isPoxyUser ?
+ UserGroupInformation.getCurrentUser().getShortUserName() : null;
try {
- if (dToken == null) {
- //TODO: need to take care of the renew case
- dToken = selectToken();
- if (LOG.isDebugEnabled()) {
- LOG.debug("Timeline delegation token: " + dToken.toString());
+ return ugi.doAs(new PrivilegedExceptionAction() {
+ @Override
+ public HttpURLConnection run() throws Exception {
+ return new DelegationTokenAuthenticatedURL(
+ authenticator, connConfigurator).openConnection(url, token,
+ doAsUser);
}
- }
- if (dToken != null) {
- Map params = new HashMap();
- TimelineAuthenticator.injectDelegationToken(params, dToken);
- url = TimelineAuthenticator.appendParams(url, params);
- if (LOG.isDebugEnabled()) {
- LOG.debug("URL with delegation token: " + url);
- }
- }
- return new AuthenticatedURL(
- authenticator, connConfigurator).openConnection(url, token);
- } catch (AuthenticationException e) {
- LOG.error("Authentication failed when openning connection [" + url
- + "] with token [" + token + "].", e);
+ });
+ } catch (UndeclaredThrowableException e) {
+ throw new IOException(e.getCause());
+ } catch (InterruptedException e) {
throw new IOException(e);
}
}
- private Token selectToken() {
- UserGroupInformation ugi;
- try {
- ugi = UserGroupInformation.getCurrentUser();
- } catch (IOException e) {
- String msg = "Error when getting the current user";
- LOG.error(msg, e);
- throw new YarnRuntimeException(msg, e);
- }
- TimelineDelegationTokenSelector tokenSelector =
- new TimelineDelegationTokenSelector();
- return tokenSelector.selectToken(
- service, ugi.getCredentials().getAllTokens());
- }
-
- public void setService(Text service) {
- this.service = service;
- }
-
}
private static ConnectionConfigurator newConnConfigurator(Configuration conf) {
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
index 41b1d4f..3c5fa867 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/client/YARNDelegationTokenIdentifier.java
@@ -38,22 +38,9 @@
public YARNDelegationTokenIdentifier() {}
public YARNDelegationTokenIdentifier(Text owner, Text renewer, Text realUser) {
- if (owner != null) {
- builder.setOwner(owner.toString());
- }
-
- if (renewer != null) {
- HadoopKerberosName renewerKrbName = new HadoopKerberosName(renewer.toString());
- try {
- builder.setRenewer(renewerKrbName.getShortName());
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- if (realUser != null) {
- builder.setRealUser(realUser.toString());
- }
+ setOwner(owner);
+ setRenewer(renewer);
+ setRealUser(realUser);
}
/**
@@ -90,6 +77,13 @@ public Text getOwner() {
}
}
+ @Override
+ public void setOwner(Text owner) {
+ if (builder != null && owner != null) {
+ builder.setOwner(owner.toString());
+ }
+ }
+
public Text getRenewer() {
String renewer = builder.getRenewer();
if (renewer == null) {
@@ -98,7 +92,19 @@ public Text getRenewer() {
return new Text(renewer);
}
}
-
+
+ @Override
+ public void setRenewer(Text renewer) {
+ if (builder != null && renewer != null) {
+ HadoopKerberosName renewerKrbName = new HadoopKerberosName(renewer.toString());
+ try {
+ builder.setRenewer(renewerKrbName.getShortName());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
public Text getRealUser() {
String realUser = builder.getRealUser();
if (realUser == null) {
@@ -107,7 +113,14 @@ public Text getRealUser() {
return new Text(realUser);
}
}
-
+
+ @Override
+ public void setRealUser(Text realUser) {
+ if (builder != null && realUser != null) {
+ builder.setRealUser(realUser.toString());
+ }
+ }
+
public void setIssueDate(long issueDate) {
builder.setIssueDate(issueDate);
}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineAuthenticator.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineAuthenticator.java
deleted file mode 100644
index 19aaa88..0000000
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/client/api/impl/TestTimelineAuthenticator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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.client.api.impl;
-
-import java.net.URL;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestTimelineAuthenticator {
-
- @Test
- public void testHasDelegationTokens() throws Exception {
- TimelineAuthenticator authenticator = new TimelineAuthenticator();
- Assert.assertFalse(authenticator.hasDelegationToken(new URL(
- "http://localhost:8/resource")));
- Assert.assertFalse(authenticator.hasDelegationToken(new URL(
- "http://localhost:8/resource?other=xxxx")));
- Assert.assertTrue(authenticator.hasDelegationToken(new URL(
- "http://localhost:8/resource?delegation=yyyy")));
- Assert.assertTrue(authenticator.hasDelegationToken(new URL(
- "http://localhost:8/resource?other=xxxx&delegation=yyyy")));
- }
-}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/pom.xml hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/pom.xml
index 71605a5..cc2d65d 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/pom.xml
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/pom.xml
@@ -159,6 +159,19 @@
org.fusesource.leveldbjnileveldbjni-all
-
+
+
+
+ org.apache.hadoop
+ hadoop-minikdc
+ test
+
+
+
+ org.apache.hadoop
+ hadoop-auth
+ test
+ test-jar
+
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryServer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryServer.java
index 87761f1..c7e305c 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryServer.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/ApplicationHistoryServer.java
@@ -45,6 +45,7 @@
import org.apache.hadoop.yarn.server.timeline.TimelineDataManager;
import org.apache.hadoop.yarn.server.timeline.TimelineStore;
import org.apache.hadoop.yarn.server.timeline.security.TimelineACLsManager;
+import org.apache.hadoop.yarn.server.timeline.security.TimelineAuthenticationFilter;
import org.apache.hadoop.yarn.server.timeline.security.TimelineAuthenticationFilterInitializer;
import org.apache.hadoop.yarn.server.timeline.security.TimelineDelegationTokenSecretManagerService;
import org.apache.hadoop.yarn.server.timeline.webapp.CrossOriginFilterInitializer;
@@ -213,6 +214,8 @@ private TimelineDataManager createTimelineDataManager(Configuration conf) {
private void startWebApp() {
Configuration conf = getConfig();
+ TimelineAuthenticationFilter.setTimelineDelegationTokenSecretManager(
+ secretManagerService.getTimelineDelegationTokenSecretManager());
// Always load pseudo authentication filter to parse "user.name" in an URL
// to identify a HTTP request's user in insecure mode.
// When Kerberos authentication type is set (i.e., secure mode is turned on),
@@ -263,15 +266,12 @@ private void startWebApp() {
WebAppUtils.getAHSWebAppURLWithoutScheme(conf));
LOG.info("Instantiating AHSWebApp at " + bindAddress);
try {
- AHSWebApp ahsWebApp = AHSWebApp.getInstance();
- ahsWebApp.setApplicationHistoryManager(historyManager);
- ahsWebApp.setTimelineDelegationTokenSecretManagerService(secretManagerService);
- ahsWebApp.setTimelineDataManager(timelineDataManager);
webApp =
WebApps
.$for("applicationhistory", ApplicationHistoryClientService.class,
ahsClientService, "ws")
- .with(conf).at(bindAddress).start(ahsWebApp);
+ .with(conf).at(bindAddress).start(
+ new AHSWebApp(timelineDataManager, historyManager));
} catch (Exception e) {
String msg = "AHSWebApp failed to start.";
LOG.error(msg, e);
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebApp.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebApp.java
index 68541d8..814752b 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebApp.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebApp.java
@@ -19,71 +19,34 @@
import static org.apache.hadoop.yarn.util.StringHelper.pajoin;
-import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.yarn.server.api.ApplicationContext;
import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryManager;
import org.apache.hadoop.yarn.server.timeline.TimelineDataManager;
-import org.apache.hadoop.yarn.server.timeline.security.TimelineDelegationTokenSecretManagerService;
import org.apache.hadoop.yarn.server.timeline.webapp.TimelineWebServices;
import org.apache.hadoop.yarn.webapp.GenericExceptionHandler;
import org.apache.hadoop.yarn.webapp.WebApp;
import org.apache.hadoop.yarn.webapp.YarnJacksonJaxbJsonProvider;
import org.apache.hadoop.yarn.webapp.YarnWebParams;
-import com.google.common.annotations.VisibleForTesting;
-
public class AHSWebApp extends WebApp implements YarnWebParams {
private ApplicationHistoryManager applicationHistoryManager;
- private TimelineDelegationTokenSecretManagerService secretManagerService;
private TimelineDataManager timelineDataManager;
- private static AHSWebApp instance = null;
-
- public static AHSWebApp getInstance() {
- if (instance == null) {
- instance = new AHSWebApp();
- }
- return instance;
- }
-
- @Private
- @VisibleForTesting
- public static void resetInstance() {
- instance = null;
- }
-
- private AHSWebApp() {
-
- }
-
- public ApplicationHistoryManager getApplicationHistoryManager() {
- return applicationHistoryManager;
- }
-
- public void setApplicationHistoryManager(
+ public AHSWebApp(TimelineDataManager timelineDataManager,
ApplicationHistoryManager applicationHistoryManager) {
+ this.timelineDataManager = timelineDataManager;
this.applicationHistoryManager = applicationHistoryManager;
}
- public TimelineDelegationTokenSecretManagerService
- getTimelineDelegationTokenSecretManagerService() {
- return secretManagerService;
- }
-
- public void setTimelineDelegationTokenSecretManagerService(
- TimelineDelegationTokenSecretManagerService secretManagerService) {
- this.secretManagerService = secretManagerService;
+ public ApplicationHistoryManager getApplicationHistoryManager() {
+ return applicationHistoryManager;
}
public TimelineDataManager getTimelineDataManager() {
return timelineDataManager;
}
- public void setTimelineDataManager(TimelineDataManager timelineDataManager) {
- this.timelineDataManager = timelineDataManager;
- }
-
@Override
public void setup() {
bind(YarnJacksonJaxbJsonProvider.class);
@@ -91,8 +54,6 @@ public void setup() {
bind(TimelineWebServices.class);
bind(GenericExceptionHandler.class);
bind(ApplicationContext.class).toInstance(applicationHistoryManager);
- bind(TimelineDelegationTokenSecretManagerService.class).toInstance(
- secretManagerService);
bind(TimelineDataManager.class).toInstance(timelineDataManager);
route("/", AHSController.class);
route(pajoin("/apps", APP_STATE), AHSController.class);
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilter.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilter.java
index 8e31362..ad8dc2c 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilter.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilter.java
@@ -18,32 +18,32 @@
package org.apache.hadoop.yarn.server.timeline.security;
-import java.util.Properties;
-
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
+import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationFilter;
+import org.apache.hadoop.yarn.server.timeline.security.TimelineDelegationTokenSecretManagerService.TimelineDelegationTokenSecretManager;
@Private
@Unstable
-public class TimelineAuthenticationFilter extends AuthenticationFilter {
+public class TimelineAuthenticationFilter
+ extends DelegationTokenAuthenticationFilter {
+
+ private static TimelineDelegationTokenSecretManager secretManager;
@Override
- protected Properties getConfiguration(String configPrefix,
- FilterConfig filterConfig) throws ServletException {
- // In yarn-site.xml, we can simply set type to "kerberos". However, we need
- // to replace the name here to use the customized Kerberos + DT service
- // instead of the standard Kerberos handler.
- Properties properties = super.getConfiguration(configPrefix, filterConfig);
- String authType = properties.getProperty(AUTH_TYPE);
- if (authType != null && authType.equals("kerberos")) {
- properties.setProperty(
- AUTH_TYPE, TimelineClientAuthenticationService.class.getName());
- }
- return properties;
+ public void init(FilterConfig filterConfig) throws ServletException {
+ filterConfig.getServletContext().setAttribute(
+ DelegationTokenAuthenticationFilter.DELEGATION_TOKEN_SECRET_MANAGER_ATTR,
+ secretManager);
+ super.init(filterConfig);
+ }
+
+ public static void setTimelineDelegationTokenSecretManager(
+ TimelineDelegationTokenSecretManager secretManager) {
+ TimelineAuthenticationFilter.secretManager = secretManager;
}
}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilterInitializer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilterInitializer.java
index 29e6c34..5e8d71e 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilterInitializer.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineAuthenticationFilterInitializer.java
@@ -30,6 +30,13 @@
import org.apache.hadoop.http.HttpServer2;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.security.SecurityUtil;
+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.delegation.web.DelegationTokenAuthenticationHandler;
+import org.apache.hadoop.security.token.delegation.web.KerberosDelegationTokenAuthenticationHandler;
+import org.apache.hadoop.security.token.delegation.web.PseudoDelegationTokenAuthenticationHandler;
+import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
/**
*
@@ -108,21 +115,33 @@ public void initFilter(FilterContainer container, Configuration conf) {
}
}
- // Resolve _HOST into bind address
- String bindAddress = conf.get(HttpServer2.BIND_ADDRESS);
- String principal =
- filterConfig.get(TimelineClientAuthenticationService.PRINCIPAL);
- if (principal != null) {
- try {
- principal = SecurityUtil.getServerPrincipal(principal, bindAddress);
- } catch (IOException ex) {
- throw new RuntimeException(
- "Could not resolve Kerberos principal name: " + ex.toString(), ex);
+ String authType = filterConfig.get(AuthenticationFilter.AUTH_TYPE);
+ if (authType.equals(PseudoAuthenticationHandler.TYPE)) {
+ filterConfig.put(AuthenticationFilter.AUTH_TYPE,
+ PseudoDelegationTokenAuthenticationHandler.class.getName());
+ } else if (authType.equals(KerberosAuthenticationHandler.TYPE)) {
+ filterConfig.put(AuthenticationFilter.AUTH_TYPE,
+ KerberosDelegationTokenAuthenticationHandler.class.getName());
+
+ // Resolve _HOST into bind address
+ String bindAddress = conf.get(HttpServer2.BIND_ADDRESS);
+ String principal =
+ filterConfig.get(KerberosAuthenticationHandler.PRINCIPAL);
+ if (principal != null) {
+ try {
+ principal = SecurityUtil.getServerPrincipal(principal, bindAddress);
+ } catch (IOException ex) {
+ throw new RuntimeException(
+ "Could not resolve Kerberos principal name: " + ex.toString(), ex);
+ }
+ filterConfig.put(KerberosAuthenticationHandler.PRINCIPAL,
+ principal);
}
- filterConfig.put(TimelineClientAuthenticationService.PRINCIPAL,
- principal);
}
+ filterConfig.put(DelegationTokenAuthenticationHandler.TOKEN_KIND,
+ TimelineDelegationTokenIdentifier.KIND_NAME.toString());
+
container.addGlobalFilter("Timeline Authentication Filter",
TimelineAuthenticationFilter.class.getName(),
filterConfig);
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineClientAuthenticationService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineClientAuthenticationService.java
deleted file mode 100644
index 9581e82..0000000
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineClientAuthenticationService.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- * 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.timeline.security;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.text.MessageFormat;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.MediaType;
-
-import org.apache.hadoop.classification.InterfaceAudience.Private;
-import org.apache.hadoop.classification.InterfaceStability.Unstable;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.security.authentication.client.AuthenticationException;
-import org.apache.hadoop.security.authentication.server.AuthenticationToken;
-import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
-import org.apache.hadoop.security.token.Token;
-import org.apache.hadoop.yarn.api.records.timeline.TimelineDelegationTokenResponse;
-import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
-import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenOperation;
-import org.apache.hadoop.yarn.security.client.TimelineAuthenticationConsts;
-import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.AHSWebApp;
-import org.apache.hadoop.yarn.webapp.YarnJacksonJaxbJsonProvider;
-import org.codehaus.jackson.map.ObjectMapper;
-
-/**
- * Server side AuthenticationHandler that authenticates requests
- * using the incoming delegation token as a 'delegation' query string parameter.
- *
- * If not delegation token is present in the request it delegates to the
- * {@link KerberosAuthenticationHandler}
- */
-@Private
-@Unstable
-public class TimelineClientAuthenticationService
- extends KerberosAuthenticationHandler {
-
- public static final String TYPE = "kerberos-dt";
- private static final Set DELEGATION_TOKEN_OPS = new HashSet();
- private static final String OP_PARAM = "op";
- private static final String ENTER = System.getProperty("line.separator");
-
- private ObjectMapper mapper;
-
- static {
- DELEGATION_TOKEN_OPS.add(
- TimelineDelegationTokenOperation.GETDELEGATIONTOKEN.toString());
- DELEGATION_TOKEN_OPS.add(
- TimelineDelegationTokenOperation.RENEWDELEGATIONTOKEN.toString());
- DELEGATION_TOKEN_OPS.add(
- TimelineDelegationTokenOperation.CANCELDELEGATIONTOKEN.toString());
- }
-
- public TimelineClientAuthenticationService() {
- super();
- mapper = new ObjectMapper();
- YarnJacksonJaxbJsonProvider.configObjectMapper(mapper);
- }
-
- /**
- * Returns authentication type of the handler.
- *
- * @return delegationtoken-kerberos
- */
- @Override
- public String getType() {
- return TYPE;
- }
-
- @Override
- public boolean managementOperation(AuthenticationToken token,
- HttpServletRequest request, HttpServletResponse response)
- throws IOException, AuthenticationException {
- boolean requestContinues = true;
- String op = request.getParameter(OP_PARAM);
- op = (op != null) ? op.toUpperCase() : null;
- if (DELEGATION_TOKEN_OPS.contains(op) &&
- !request.getMethod().equals("OPTIONS")) {
- TimelineDelegationTokenOperation dtOp =
- TimelineDelegationTokenOperation.valueOf(op);
- if (dtOp.getHttpMethod().equals(request.getMethod())) {
- if (dtOp.requiresKerberosCredentials() && token == null) {
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
- MessageFormat.format(
- "Operation [{0}] requires SPNEGO authentication established",
- dtOp));
- requestContinues = false;
- } else {
- TimelineDelegationTokenSecretManagerService secretManager =
- AHSWebApp.getInstance()
- .getTimelineDelegationTokenSecretManagerService();
- try {
- TimelineDelegationTokenResponse res = null;
- switch (dtOp) {
- case GETDELEGATIONTOKEN:
- UserGroupInformation ownerUGI =
- UserGroupInformation.createRemoteUser(token.getUserName());
- String renewerParam =
- request
- .getParameter(TimelineAuthenticationConsts.RENEWER_PARAM);
- if (renewerParam == null) {
- renewerParam = token.getUserName();
- }
- Token> dToken =
- secretManager.createToken(ownerUGI, renewerParam);
- res = new TimelineDelegationTokenResponse();
- res.setType(TimelineAuthenticationConsts.DELEGATION_TOKEN_URL);
- res.setContent(dToken.encodeToUrlString());
- break;
- case RENEWDELEGATIONTOKEN:
- case CANCELDELEGATIONTOKEN:
- String tokenParam =
- request
- .getParameter(TimelineAuthenticationConsts.TOKEN_PARAM);
- if (tokenParam == null) {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST,
- MessageFormat
- .format(
- "Operation [{0}] requires the parameter [{1}]",
- dtOp,
- TimelineAuthenticationConsts.TOKEN_PARAM));
- requestContinues = false;
- } else {
- if (dtOp == TimelineDelegationTokenOperation.CANCELDELEGATIONTOKEN) {
- Token dt =
- new Token();
- dt.decodeFromUrlString(tokenParam);
- secretManager.cancelToken(dt, token.getUserName());
- } else {
- Token dt =
- new Token();
- dt.decodeFromUrlString(tokenParam);
- long expirationTime =
- secretManager.renewToken(dt, token.getUserName());
- res = new TimelineDelegationTokenResponse();
- res.setType(TimelineAuthenticationConsts.DELEGATION_TOKEN_EXPIRATION_TIME);
- res.setContent(expirationTime);
- }
- }
- break;
- }
- if (requestContinues) {
- response.setStatus(HttpServletResponse.SC_OK);
- if (res != null) {
- response.setContentType(MediaType.APPLICATION_JSON);
- Writer writer = response.getWriter();
- mapper.writeValue(writer, res);
- writer.write(ENTER);
- writer.flush();
-
- }
- requestContinues = false;
- }
- } catch (IOException e) {
- throw new AuthenticationException(e.toString(), e);
- }
- }
- } else {
- response
- .sendError(
- HttpServletResponse.SC_BAD_REQUEST,
- MessageFormat
- .format(
- "Wrong HTTP method [{0}] for operation [{1}], it should be [{2}]",
- request.getMethod(), dtOp, dtOp.getHttpMethod()));
- requestContinues = false;
- }
- }
- return requestContinues;
- }
-
- /**
- * Authenticates a request looking for the delegation
- * query-string parameter and verifying it is a valid token. If there is not
- * delegation query-string parameter, it delegates the
- * authentication to the {@link KerberosAuthenticationHandler} unless it is
- * disabled.
- *
- * @param request
- * the HTTP client request.
- * @param response
- * the HTTP client response.
- *
- * @return the authentication token for the authenticated request.
- * @throws IOException
- * thrown if an IO error occurred.
- * @throws AuthenticationException
- * thrown if the authentication failed.
- */
- @Override
- public AuthenticationToken authenticate(HttpServletRequest request,
- HttpServletResponse response)
- throws IOException, AuthenticationException {
- AuthenticationToken token;
- String delegationParam =
- request
- .getParameter(TimelineAuthenticationConsts.DELEGATION_PARAM);
- if (delegationParam != null) {
- Token dt =
- new Token();
- dt.decodeFromUrlString(delegationParam);
- TimelineDelegationTokenSecretManagerService secretManager =
- AHSWebApp.getInstance()
- .getTimelineDelegationTokenSecretManagerService();
- UserGroupInformation ugi = secretManager.verifyToken(dt);
- final String shortName = ugi.getShortUserName();
- // creating a ephemeral token
- token = new AuthenticationToken(shortName, ugi.getUserName(), getType());
- token.setExpires(0);
- } else {
- token = super.authenticate(request, response);
- }
- return token;
- }
-
-}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineDelegationTokenSecretManagerService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineDelegationTokenSecretManagerService.java
index 1539513..11a64e6 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineDelegationTokenSecretManagerService.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/security/TimelineDelegationTokenSecretManagerService.java
@@ -77,73 +77,11 @@ protected void serviceStop() throws Exception {
}
/**
- * Creates a delegation token.
- *
- * @param ugi UGI creating the token.
- * @param renewer token renewer.
- * @return new delegation token.
- * @throws IOException thrown if the token could not be created.
+ * Ge the instance of {link #TimelineDelegationTokenSecretManager}
+ * @return the instance of {link #TimelineDelegationTokenSecretManager}
*/
- public Token createToken(
- UserGroupInformation ugi, String renewer) throws IOException {
- renewer = (renewer == null) ? ugi.getShortUserName() : renewer;
- String user = ugi.getUserName();
- Text owner = new Text(user);
- Text realUser = null;
- if (ugi.getRealUser() != null) {
- realUser = new Text(ugi.getRealUser().getUserName());
- }
- TimelineDelegationTokenIdentifier tokenIdentifier =
- new TimelineDelegationTokenIdentifier(owner, new Text(renewer), realUser);
- Token token =
- new Token(tokenIdentifier, secretManager);
- SecurityUtil.setTokenService(token, serviceAddr);
- return token;
- }
-
- /**
- * Renews a delegation token.
- *
- * @param token delegation token to renew.
- * @param renewer token renewer.
- * @throws IOException thrown if the token could not be renewed.
- */
- public long renewToken(Token token,
- String renewer) throws IOException {
- return secretManager.renewToken(token, renewer);
- }
-
- /**
- * Cancels a delegation token.
- *
- * @param token delegation token to cancel.
- * @param canceler token canceler.
- * @throws IOException thrown if the token could not be canceled.
- */
- public void cancelToken(Token token,
- String canceler) throws IOException {
- secretManager.cancelToken(token, canceler);
- }
-
- /**
- * Verifies a delegation token.
- *
- * @param token delegation token to verify.
- * @return the UGI for the token.
- * @throws IOException thrown if the token could not be verified.
- */
- public UserGroupInformation verifyToken(Token token)
- throws IOException {
- ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier());
- DataInputStream dis = new DataInputStream(buf);
- TimelineDelegationTokenIdentifier id = new TimelineDelegationTokenIdentifier();
- try {
- id.readFields(dis);
- secretManager.verifyToken(id, token.getPassword());
- } finally {
- dis.close();
- }
- return id.getUser();
+ public TimelineDelegationTokenSecretManager getTimelineDelegationTokenSecretManager() {
+ return secretManager;
}
/**
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryClientService.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryClientService.java
index ad2907b..be8cefb 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryClientService.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryClientService.java
@@ -76,7 +76,6 @@ public void setup() {
@After
public void tearDown() throws Exception {
- AHSWebApp.resetInstance();
historyServer.stop();
}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryServer.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryServer.java
index 8231341..b11cda7 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryServer.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/TestApplicationHistoryServer.java
@@ -105,7 +105,6 @@ public void testFilteOverrides() throws Exception {
Configuration tmp = historyServer.getConfig();
assertEquals(expectedValue, tmp.get("hadoop.http.filter.initializers"));
historyServer.stop();
- AHSWebApp.resetInstance();
}
}
@@ -114,6 +113,5 @@ public void stop() {
if (historyServer != null) {
historyServer.stop();
}
- AHSWebApp.resetInstance();
}
}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java
new file mode 100644
index 0000000..3477570
--- /dev/null
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java
@@ -0,0 +1,217 @@
+/**
+ * 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.timeline.security;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.Callable;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.minikdc.MiniKdc;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authentication.KerberosTestUtils;
+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.yarn.api.records.timeline.TimelineEntity;
+import org.apache.hadoop.yarn.api.records.timeline.TimelinePutResponse;
+import org.apache.hadoop.yarn.client.api.TimelineClient;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
+import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryServer;
+import org.apache.hadoop.yarn.server.timeline.MemoryTimelineStore;
+import org.apache.hadoop.yarn.server.timeline.TimelineStore;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestTimelineAuthenticationFilter {
+
+ private static final String FOO_USER = "foo";
+ private static final String BAR_USER = "bar";
+ private static final String HTTP_USER = "HTTP";
+
+ private static final File testRootDir = new File("target",
+ TestTimelineAuthenticationFilter.class.getName() + "-root");
+ private static File httpSpnegoKeytabFile = new File(
+ KerberosTestUtils.getKeytabFile());
+ private static String httpSpnegoPrincipal =
+ KerberosTestUtils.getServerPrincipal();
+ private static MiniKdc testMiniKDC;
+ private static ApplicationHistoryServer testTimelineServer;
+ private static Configuration conf;
+
+ @BeforeClass
+ public static void setupClass() {
+ try {
+ testMiniKDC = new MiniKdc(MiniKdc.createConf(), testRootDir);
+ testMiniKDC.start();
+ testMiniKDC.createPrincipal(
+ httpSpnegoKeytabFile, HTTP_USER + "/localhost");
+ } catch (Exception e) {
+ assertTrue("Couldn't setup MiniKDC", false);
+ }
+
+ try {
+ testTimelineServer = new ApplicationHistoryServer();
+ conf = new YarnConfiguration();
+ conf.setStrings(TimelineAuthenticationFilterInitializer.PREFIX + "type",
+ "kerberos");
+ conf.set(TimelineAuthenticationFilterInitializer.PREFIX +
+ KerberosAuthenticationHandler.PRINCIPAL, httpSpnegoPrincipal);
+ conf.set(TimelineAuthenticationFilterInitializer.PREFIX +
+ KerberosAuthenticationHandler.KEYTAB,
+ httpSpnegoKeytabFile.getAbsolutePath());
+ conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
+ "kerberos");
+ conf.set(YarnConfiguration.TIMELINE_SERVICE_PRINCIPAL,
+ httpSpnegoPrincipal);
+ conf.set(YarnConfiguration.TIMELINE_SERVICE_KEYTAB,
+ httpSpnegoKeytabFile.getAbsolutePath());
+ conf.setBoolean(YarnConfiguration.TIMELINE_SERVICE_ENABLED, true);
+ conf.setClass(YarnConfiguration.TIMELINE_SERVICE_STORE,
+ MemoryTimelineStore.class, TimelineStore.class);
+ conf.set(YarnConfiguration.TIMELINE_SERVICE_ADDRESS,
+ "localhost:10200");
+ conf.set(YarnConfiguration.TIMELINE_SERVICE_WEBAPP_ADDRESS,
+ "localhost:8188");
+ conf.set(TimelineAuthenticationFilterInitializer.PREFIX +
+ "proxyuser.HTTP.hosts", "*");
+ conf.set(TimelineAuthenticationFilterInitializer.PREFIX +
+ "proxyuser.HTTP.users", FOO_USER);
+ UserGroupInformation.setConfiguration(conf);
+ testTimelineServer.init(conf);
+ testTimelineServer.start();
+ } catch (Exception e) {
+ assertTrue("Couldn't setup TimelineServer", false);
+ }
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ if (testMiniKDC != null) {
+ testMiniKDC.stop();
+ }
+
+ if (testTimelineServer != null) {
+ testTimelineServer.stop();
+ }
+ }
+
+ private TimelineClient client;
+
+ @Before
+ public void setup() throws Exception {
+ client = TimelineClient.createTimelineClient();
+ client.init(conf);
+ client.start();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (client != null) {
+ client.stop();
+ }
+ }
+
+ @Test
+ public void testPutTimelineEntities() throws Exception {
+ KerberosTestUtils.doAs(HTTP_USER + "/localhost", new Callable() {
+ @Override
+ public Void call() throws Exception {
+ TimelineEntity entityToStore = new TimelineEntity();
+ entityToStore.setEntityType("TestTimelineAuthenticationFilter");
+ entityToStore.setEntityId("entity1");
+ entityToStore.setStartTime(0L);
+ TimelinePutResponse putResponse = client.putEntities(entityToStore);
+ Assert.assertEquals(0, putResponse.getErrors().size());
+ TimelineEntity entityToRead =
+ testTimelineServer.getTimelineStore().getEntity(
+ "entity1", "TestTimelineAuthenticationFilter", null);
+ Assert.assertNotNull(entityToRead);
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testGetDelegationToken() throws Exception {
+ KerberosTestUtils.doAs(HTTP_USER + "/localhost", new Callable() {
+ @Override
+ public Void call() throws Exception {
+ // Let HTTP user to get the delegation for itself
+ Token token =
+ client.getDelegationToken(
+ UserGroupInformation.getCurrentUser().getShortUserName());
+ Assert.assertNotNull(token);
+ TimelineDelegationTokenIdentifier tDT = token.decodeIdentifier();
+ Assert.assertNotNull(tDT);
+ Assert.assertEquals(new Text(HTTP_USER), tDT.getOwner());
+
+ // Let HTTP user to get the delegation token for FOO user
+ UserGroupInformation fooUgi = UserGroupInformation.createProxyUser(
+ FOO_USER, UserGroupInformation.getCurrentUser());
+ token = fooUgi.doAs(
+ new PrivilegedExceptionAction>() {
+ @Override
+ public Token run()
+ throws Exception {
+ return client.getDelegationToken(
+ UserGroupInformation.getCurrentUser().getShortUserName());
+ }
+ });
+ Assert.assertNotNull(token);
+ tDT = token.decodeIdentifier();
+ Assert.assertNotNull(tDT);
+ Assert.assertEquals(new Text(FOO_USER), tDT.getOwner());
+ Assert.assertEquals(new Text(HTTP_USER), tDT.getRealUser());
+
+ // Let HTTP user to get the delegation token for BAR user
+ UserGroupInformation barUgi = UserGroupInformation.createProxyUser(
+ BAR_USER, UserGroupInformation.getCurrentUser());
+ token = barUgi.doAs(
+ new PrivilegedExceptionAction>() {
+ @Override
+ public Token run()
+ throws Exception {
+ try {
+ Token token =
+ client.getDelegationToken(
+ UserGroupInformation.getCurrentUser().getShortUserName());
+ Assert.fail();
+ return token;
+ } catch (Exception e) {
+ Assert.assertTrue(e instanceof AuthorizationException);
+ return null;
+ }
+ }
+ });
+ return null;
+ }
+ });
+ }
+
+}
diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestTimelineWebServices.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestTimelineWebServices.java
index f429a97..a244bb2 100644
--- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestTimelineWebServices.java
+++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestTimelineWebServices.java
@@ -42,6 +42,7 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
+import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationHandler;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEntities;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEntity;
import org.apache.hadoop.yarn.api.records.timeline.TimelineEvent;
@@ -52,6 +53,7 @@
import org.apache.hadoop.yarn.api.records.timeline.TimelinePutResponse.TimelinePutError;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.security.AdminACLsManager;
+import org.apache.hadoop.yarn.security.client.TimelineDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.timeline.TestMemoryTimelineStore;
import org.apache.hadoop.yarn.server.timeline.TimelineDataManager;
import org.apache.hadoop.yarn.server.timeline.TimelineStore;
@@ -118,11 +120,15 @@ protected void configureServlets() {
ServletContext context = mock(ServletContext.class);
when(filterConfig.getServletContext()).thenReturn(context);
Enumeration