diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationWithProxyUserFilter.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationWithProxyUserFilter.java
index ea9b282ab89..751cf02ca54 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationWithProxyUserFilter.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationWithProxyUserFilter.java
@@ -17,10 +17,11 @@
*/
package org.apache.hadoop.security;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.authorize.ProxyUsers;
-import org.apache.hadoop.util.HttpExceptionUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
@@ -41,6 +42,9 @@ import java.util.List;
*/
public class AuthenticationWithProxyUserFilter extends AuthenticationFilter {
+ public static final Log LOG =
+ LogFactory.getLog(AuthenticationWithProxyUserFilter.class);
+
/**
* Constant used in URL's query string to perform a proxy user request, the
* value of the DO_AS
parameter is the user the request will be
@@ -66,29 +70,30 @@ public class AuthenticationWithProxyUserFilter extends AuthenticationFilter {
protected void doFilter(FilterChain filterChain, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
- // authorize proxy user before calling next filter.
- String proxyUser = getDoAs(request);
+ final String proxyUser = getDoAs(request);
if (proxyUser != null) {
- UserGroupInformation realUser =
- UserGroupInformation.createRemoteUser(request.getRemoteUser());
- UserGroupInformation proxyUserInfo =
- UserGroupInformation.createProxyUser(proxyUser, realUser);
- try {
- ProxyUsers.authorize(proxyUserInfo, request.getRemoteAddr());
- } catch (AuthorizationException ex) {
- HttpExceptionUtils.createServletExceptionResponse(response,
- HttpServletResponse.SC_FORBIDDEN, ex);
- // stop filter chain if there is an Authorization Exception.
- return;
- }
-
- final UserGroupInformation finalProxyUser = proxyUserInfo;
// Change the remote user after proxy user is authorized.
- request = new HttpServletRequestWrapper(request) {
+ final HttpServletRequest finalReq = request;
+ request = new HttpServletRequestWrapper(finalReq) {
+
+ private String getRemoteOrProxyUser() throws AuthorizationException {
+ UserGroupInformation realUser =
+ UserGroupInformation.createRemoteUser(finalReq.getRemoteUser());
+ UserGroupInformation proxyUserInfo =
+ UserGroupInformation.createProxyUser(proxyUser, realUser);
+ ProxyUsers.authorize(proxyUserInfo, finalReq.getRemoteAddr());
+ return proxyUserInfo.getUserName();
+ }
+
@Override
public String getRemoteUser() {
- return finalProxyUser.getUserName();
+ try {
+ return getRemoteOrProxyUser();
+ } catch (AuthorizationException ex) {
+ LOG.error("Unable to verify proxy user: " + ex.getMessage(), ex);
+ }
+ return null;
}
};
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
index cbdda907d02..3d3e020f412 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/http/TestHttpServerWithSpengo.java
@@ -157,12 +157,25 @@ public class TestHttpServerWithSpengo {
Assert.assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
}
- // userA cannot impersonate userC, it fails.
+ // userA cannot impersonate userC, but for /stacks, /jmx and /conf,
+ // they doesn't require users to authorize by default, so they
+ // can be accessed.
for (String servlet :
new String[]{"stacks", "jmx", "conf"}){
HttpURLConnection conn = authUrl
.openConnection(new URL(serverURL + servlet + "?doAs=userC"),
token);
+ Assert.assertEquals(HttpURLConnection.HTTP_OK,
+ conn.getResponseCode());
+ }
+
+ // "/logs" and "/logLevel" require admin authorization,
+ // only userA has the access.
+ for (String servlet :
+ new String[]{"logLevel", "logs"}) {
+ HttpURLConnection conn = authUrl
+ .openConnection(new URL(serverURL + servlet + "?doAs=userC"),
+ token);
Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN,
conn.getResponseCode());
}
diff --git a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java
index e30e1b907dd..1c90cb9d172 100644
--- a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java
+++ b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java
@@ -392,10 +392,11 @@ public class AppController extends Controller implements AMParams {
*/
boolean checkAccess(Job job) {
String remoteUser = request().getRemoteUser();
- UserGroupInformation callerUGI = null;
- if (remoteUser != null) {
- callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
+ if (remoteUser == null) {
+ return false;
}
+ UserGroupInformation callerUGI =
+ UserGroupInformation.createRemoteUser(remoteUser);
if (callerUGI != null && !job.checkAccess(callerUGI, JobACL.VIEW_JOB)) {
return false;
}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java
index 349a98c97f7..11bd9b47185 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java
@@ -31,6 +31,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.http.RestCsrfPreventionFilter;
import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.api.ApplicationBaseProtocol;
@@ -100,8 +101,8 @@ public class AppBlock extends HtmlBlock {
final GetApplicationReportRequest request =
GetApplicationReportRequest.newInstance(appID);
if (callerUGI == null) {
- appReport =
- appBaseProt.getApplicationReport(request).getApplicationReport();
+ throw new AuthenticationException(
+ "Failed to get user name from request");
} else {
appReport = callerUGI.doAs(
new PrivilegedExceptionAction () {
@@ -165,36 +166,76 @@ public class AppBlock extends HtmlBlock {
String schedulerPath = WebAppUtils.getResolvedRMWebAppURLWithScheme(conf) +
"/cluster/scheduler?openQueues=" + app.getQueue();
+ generateOverviewTable(app, schedulerPath, webUiType, appReport);
+
+ Collection attempts;
+ try {
+ final GetApplicationAttemptsRequest request =
+ GetApplicationAttemptsRequest.newInstance(appID);
+ attempts = callerUGI.doAs(
+ new PrivilegedExceptionAction>() {
+ @Override
+ public Collection run() throws Exception {
+ return appBaseProt.getApplicationAttempts(request)
+ .getApplicationAttemptList();
+ }
+ });
+ } catch (Exception e) {
+ String message =
+ "Failed to read the attempts of the application " + appID + ".";
+ LOG.error(message, e);
+ html.p()._(message)._();
+ return;
+ }
+
+ createApplicationMetricsTable(html);
+
+ html._(InfoBlock.class);
+
+ generateApplicationTable(html, callerUGI, attempts);
+
+ }
+
+ /**
+ * Generate overview table for app web page.
+ * @param app app info.
+ * @param schedulerPath schedule path.
+ * @param webUiType web ui type.
+ * @param appReport app report.
+ */
+ private void generateOverviewTable(AppInfo app, String schedulerPath,
+ String webUiType, ApplicationReport appReport) {
ResponseInfo overviewTable = info("Application Overview")
- ._("User:", schedulerPath, app.getUser())
- ._("Name:", app.getName())
- ._("Application Type:", app.getType())
- ._("Application Tags:",
- app.getApplicationTags() == null ? "" : app.getApplicationTags())
- ._("Application Priority:", clarifyAppPriority(app.getPriority()))
- ._(
- "YarnApplicationState:",
- app.getAppState() == null ? UNAVAILABLE : clarifyAppState(app
- .getAppState()))
- ._("Queue:", schedulerPath, app.getQueue())
- ._("FinalStatus Reported by AM:",
- clairfyAppFinalStatus(app.getFinalAppStatus()))
- ._("Started:", Times.format(app.getStartedTime()))
- ._(
- "Elapsed:",
- StringUtils.formatTime(Times.elapsed(app.getStartedTime(),
- app.getFinishedTime())))
- ._(
- "Tracking URL:",
- app.getTrackingUrl() == null
- || app.getTrackingUrl().equals(UNAVAILABLE) ? null : root_url(app
- .getTrackingUrl()),
- app.getTrackingUrl() == null
- || app.getTrackingUrl().equals(UNAVAILABLE) ? "Unassigned" : app
- .getAppState() == YarnApplicationState.FINISHED
- || app.getAppState() == YarnApplicationState.FAILED
- || app.getAppState() == YarnApplicationState.KILLED ? "History"
- : "ApplicationMaster");
+ ._("User:", schedulerPath, app.getUser())
+ ._("Name:", app.getName())
+ ._("Application Type:", app.getType())
+ ._("Application Tags:",
+ app.getApplicationTags() == null ? "" : app.getApplicationTags())
+ ._("Application Priority:", clarifyAppPriority(app.getPriority()))
+ ._(
+ "YarnApplicationState:",
+ app.getAppState() == null ? UNAVAILABLE : clarifyAppState(app
+ .getAppState()))
+ ._("Queue:", schedulerPath, app.getQueue())
+ ._("FinalStatus Reported by AM:",
+ clairfyAppFinalStatus(app.getFinalAppStatus()))
+ ._("Started:", Times.format(app.getStartedTime()))
+ ._(
+ "Elapsed:",
+ StringUtils.formatTime(Times.elapsed(app.getStartedTime(),
+ app.getFinishedTime())))
+ ._(
+ "Tracking URL:",
+ app.getTrackingUrl() == null
+ || app.getTrackingUrl().equals(UNAVAILABLE) ? null : root_url(app
+ .getTrackingUrl()),
+ app.getTrackingUrl() == null
+ || app.getTrackingUrl().equals(UNAVAILABLE) ? "Unassigned" : app
+ .getAppState() == YarnApplicationState.FINISHED
+ || app.getAppState() == YarnApplicationState.FAILED
+ || app.getAppState() == YarnApplicationState.KILLED ? "History"
+ : "ApplicationMaster");
if (webUiType != null
&& webUiType.equals(YarnWebParams.RM_WEB_UI)) {
LogAggregationStatus status = getLogAggregationStatus();
@@ -226,38 +267,6 @@ public class AppBlock extends HtmlBlock {
overviewTable._("AM container Node Label expression:",
app.getAmNodeLabelExpression() == null ? ""
: app.getAmNodeLabelExpression());
-
- Collection attempts;
- try {
- final GetApplicationAttemptsRequest request =
- GetApplicationAttemptsRequest.newInstance(appID);
- if (callerUGI == null) {
- attempts = appBaseProt.getApplicationAttempts(request)
- .getApplicationAttemptList();
- } else {
- attempts = callerUGI.doAs(
- new PrivilegedExceptionAction> () {
- @Override
- public Collection run() throws Exception {
- return appBaseProt.getApplicationAttempts(request)
- .getApplicationAttemptList();
- }
- });
- }
- } catch (Exception e) {
- String message =
- "Failed to read the attempts of the application " + appID + ".";
- LOG.error(message, e);
- html.p()._(message)._();
- return;
- }
-
- createApplicationMetricsTable(html);
-
- html._(InfoBlock.class);
-
- generateApplicationTable(html, callerUGI, attempts);
-
}
protected void generateApplicationTable(Block html,