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(MapURL.
- *
- * @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, MapHttpURLConnection. 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..e39473b 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,15 @@
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 +62,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 +81,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 +98,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 +117,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 +140,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 +199,34 @@ private ClientResponse doPosting(Object obj, String path) throws IOException, Ya
return resp;
}
+ @SuppressWarnings("unchecked")
@Override
public Token
@@ -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.
- *
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) {
- Tokendelegation
- * 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