YARN-5294. Pass remote ip address down to YarnAuthorizationProvider. (Jian He via wangda)

This commit is contained in:
Wangda Tan 2016-07-06 16:42:35 -07:00
parent c3d9ac82af
commit e246cf74c9
8 changed files with 67 additions and 18 deletions

View File

@ -18,8 +18,12 @@
package org.apache.hadoop.yarn.security;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.security.UserGroupInformation;
import java.util.List;
/**
* This request object contains all the context information to determine whether
* a user has permission to access the target entity.
@ -30,7 +34,14 @@
* if no app is associated.
* appName : the associated app name for current access. This could be null if
* no app is associated.
* remoteAddress : The caller's remote ip address.
* forwardedAddresses : In case this is an http request, this contains the
* originating IP address of a client connecting to a web
* server through an HTTP proxy or load balancer. This
* parameter is null, if it's a RPC request.
*/
@Public
@Unstable
public class AccessRequest {
private PrivilegedEntity entity;
@ -38,14 +49,19 @@ public class AccessRequest {
private AccessType accessType;
private String appId;
private String appName;
private String remoteAddress;
private List<String> forwardedAddresses;
public AccessRequest(PrivilegedEntity entity, UserGroupInformation user,
AccessType accessType, String appId, String appName) {
AccessType accessType, String appId, String appName, String remoteAddress,
List<String> forwardedAddresses) {
this.entity = entity;
this.user = user;
this.accessType = accessType;
this.appId = appId;
this.appName = appName;
this.remoteAddress = remoteAddress;
this.forwardedAddresses = forwardedAddresses;
}
public UserGroupInformation getUser() {
@ -67,4 +83,13 @@ public String getAppName() {
public PrivilegedEntity getEntity() {
return entity;
}
public List<String> getForwardedAddresses() {
return forwardedAddresses;
}
public String getRemoteAddress() {
return remoteAddress;
}
}

View File

@ -306,7 +306,8 @@ private boolean checkAccess(UserGroupInformation callerUGI, String owner,
return applicationsACLsManager
.checkAccess(callerUGI, operationPerformed, owner,
application.getApplicationId()) || queueACLsManager
.checkAccess(callerUGI, QueueACL.ADMINISTER_QUEUE, application);
.checkAccess(callerUGI, QueueACL.ADMINISTER_QUEUE, application,
Server.getRemoteAddress(), null);
}
ApplicationId getNewApplicationId() {

View File

@ -26,6 +26,7 @@
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.DataInputByteBuffer;
import org.apache.hadoop.ipc.Server;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.UserGroupInformation;
@ -370,11 +371,13 @@ private RMAppImpl createAndPopulateNewRMApp(
&& !authorizer.checkPermission(
new AccessRequest(csqueue.getPrivilegedEntity(), userUgi,
SchedulerUtils.toAccessType(QueueACL.SUBMIT_APPLICATIONS),
applicationId.toString(), appName))
applicationId.toString(), appName, Server.getRemoteAddress(),
null))
&& !authorizer.checkPermission(
new AccessRequest(csqueue.getPrivilegedEntity(), userUgi,
SchedulerUtils.toAccessType(QueueACL.ADMINISTER_QUEUE),
applicationId.toString(), appName))) {
applicationId.toString(), appName, Server.getRemoteAddress(),
null))) {
throw new AccessControlException(
"User " + user + " does not have permission to submit "
+ applicationId + " to queue " + submissionContext.getQueue());

View File

@ -29,6 +29,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.ipc.Server;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.yarn.api.records.Priority;
@ -199,7 +200,7 @@ public Set<String> getAccessibleNodeLabels() {
public boolean hasAccess(QueueACL acl, UserGroupInformation user) {
return authorizer.checkPermission(
new AccessRequest(queueEntity, user, SchedulerUtils.toAccessType(acl),
null, null));
null, null, Server.getRemoteAddress(), null));
}
@Override

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.yarn.server.resourcemanager.security;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@ -26,15 +27,14 @@
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.security.AccessRequest;
import org.apache.hadoop.yarn.security.YarnAuthorizationProvider;
import org.apache.hadoop.yarn.server.resourcemanager.ResourceTrackerService;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerUtils;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CSQueue;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler;
import java.util.List;
public class QueueACLsManager {
private static final Log LOG = LogFactory.getLog(QueueACLsManager.class);
@ -56,7 +56,7 @@ public QueueACLsManager(ResourceScheduler scheduler, Configuration conf) {
}
public boolean checkAccess(UserGroupInformation callerUGI, QueueACL acl,
RMApp app) {
RMApp app, String remoteAddress, List<String> forwardedAddresses) {
if (!isACLsEnable) {
return true;
}
@ -71,11 +71,11 @@ public boolean checkAccess(UserGroupInformation callerUGI, QueueACL acl,
.getApplicationId());
return true;
}
return authorizer.checkPermission(
new AccessRequest(queue.getPrivilegedEntity(), callerUGI,
SchedulerUtils.toAccessType(acl),
app.getApplicationId().toString(), app.getName()));
app.getApplicationId().toString(), app.getName(),
remoteAddress, forwardedAddresses));
} else {
return scheduler.checkAccess(callerUGI, acl, app.getQueue());
}

View File

@ -25,6 +25,7 @@
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
@ -228,12 +229,18 @@ public RMWebServices(final ResourceManager rm, Configuration conf) {
protected Boolean hasAccess(RMApp app, HttpServletRequest hsr) {
// Check for the authorization.
UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
List<String> forwardedAddresses = null;
String forwardedFor = hsr.getHeader("X-Forwarded-For");
if (forwardedFor != null) {
forwardedAddresses = Arrays.asList(forwardedFor.split(","));
}
if (callerUGI != null
&& !(this.rm.getApplicationACLsManager().checkAccess(callerUGI,
ApplicationAccessType.VIEW_APP, app.getUser(),
app.getApplicationId()) ||
this.rm.getQueueACLsManager().checkAccess(callerUGI,
QueueACL.ADMINISTER_QUEUE, app))) {
QueueACL.ADMINISTER_QUEUE, app, hsr.getRemoteAddr(),
forwardedAddresses))) {
return false;
}
return true;

View File

@ -66,6 +66,7 @@
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@ -112,7 +113,8 @@ protected QueueACLsManager createQueueACLsManager(
Configuration conf) {
QueueACLsManager mockQueueACLsManager = mock(QueueACLsManager.class);
when(mockQueueACLsManager.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenAnswer(new Answer() {
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any())).thenAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
return isQueueUser;
}

View File

@ -151,6 +151,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.mockito.Matchers;
public class TestClientRMService {
@ -474,7 +475,8 @@ public void handle(Event event) {
QueueACLsManager mockQueueACLsManager = mock(QueueACLsManager.class);
when(
mockQueueACLsManager.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenReturn(true);
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any())).thenReturn(true);
return new ClientRMService(rmContext, yarnScheduler, appManager,
mockAclsManager, mockQueueACLsManager, null);
}
@ -575,7 +577,9 @@ public void testGetQueueInfo() throws Exception {
ApplicationACLsManager mockAclsManager = mock(ApplicationACLsManager.class);
QueueACLsManager mockQueueACLsManager = mock(QueueACLsManager.class);
when(mockQueueACLsManager.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenReturn(true);
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any()))
.thenReturn(true);
when(mockAclsManager.checkAccess(any(UserGroupInformation.class),
any(ApplicationAccessType.class), anyString(),
any(ApplicationId.class))).thenReturn(true);
@ -601,7 +605,9 @@ public void testGetQueueInfo() throws Exception {
QueueACLsManager mockQueueACLsManager1 =
mock(QueueACLsManager.class);
when(mockQueueACLsManager1.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenReturn(false);
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any()))
.thenReturn(false);
when(mockAclsManager1.checkAccess(any(UserGroupInformation.class),
any(ApplicationAccessType.class), anyString(),
any(ApplicationId.class))).thenReturn(false);
@ -640,7 +646,9 @@ public void handle(Event event) {}
QueueACLsManager mockQueueACLsManager = mock(QueueACLsManager.class);
when(mockQueueACLsManager.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenReturn(true);
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any()))
.thenReturn(true);
ClientRMService rmService =
new ClientRMService(rmContext, yarnScheduler, appManager,
mockAclsManager, mockQueueACLsManager, null);
@ -728,7 +736,9 @@ public void handle(Event event) {}
ApplicationACLsManager mockAclsManager = mock(ApplicationACLsManager.class);
QueueACLsManager mockQueueACLsManager = mock(QueueACLsManager.class);
when(mockQueueACLsManager.checkAccess(any(UserGroupInformation.class),
any(QueueACL.class), any(RMApp.class))).thenReturn(true);
any(QueueACL.class), any(RMApp.class), any(String.class),
Matchers.<List<String>>any()))
.thenReturn(true);
ClientRMService rmService =
new ClientRMService(rmContext, yarnScheduler, appManager,
mockAclsManager, mockQueueACLsManager, null);