diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessRequest.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessRequest.java index 8292f4e..003bdd1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessRequest.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/AccessRequest.java @@ -20,6 +20,8 @@ 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. @@ -38,14 +40,19 @@ private AccessType accessType; private String appId; private String appName; + private List forwardedAddresses; + private String remoteAddress; public AccessRequest(PrivilegedEntity entity, UserGroupInformation user, - AccessType accessType, String appId, String appName) { + AccessType accessType, String appId, String appName, String remoteAddress, + List 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 +74,13 @@ public String getAppName() { public PrivilegedEntity getEntity() { return entity; } + + + public List getForwardedAddresses() { + return forwardedAddresses; + } + + public String getRemoteAddress() { + return remoteAddress; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java index ec5faeb..7263e01 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ClientRMService.java @@ -306,7 +306,7 @@ 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, null); } ApplicationId getNewApplicationId() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java index 78d6ebe..279f0b3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java @@ -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()); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java index dc90c5b..9c88154 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java @@ -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 synchronized void setParent(CSQueue newParentQueue) { 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 diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java index 15c7052..be9797e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/QueueACLsManager.java @@ -21,12 +21,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.ipc.Server; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.api.records.QueueACL; 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; @@ -35,6 +35,10 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CSQueue; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler; +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; + public class QueueACLsManager { private static final Log LOG = LogFactory.getLog(QueueACLsManager.class); @@ -56,7 +60,7 @@ public QueueACLsManager(ResourceScheduler scheduler, Configuration conf) { } public boolean checkAccess(UserGroupInformation callerUGI, QueueACL acl, - RMApp app) { + RMApp app, HttpServletRequest request) { if (!isACLsEnable) { return true; } @@ -72,10 +76,18 @@ public boolean checkAccess(UserGroupInformation callerUGI, QueueACL acl, return true; } + List forwardedAddresses = null; + if (request != null) { + String forwardedFor = request.getHeader("X-Forwarded-For"); + if (forwardedFor != null) { + forwardedAddresses = Arrays.asList(forwardedFor.split(",")); + } + } return authorizer.checkPermission( new AccessRequest(queue.getPrivilegedEntity(), callerUGI, SchedulerUtils.toAccessType(acl), - app.getApplicationId().toString(), app.getName())); + app.getApplicationId().toString(), app.getName(), + Server.getRemoteAddress(), forwardedAddresses)); } else { return scheduler.checkAccess(callerUGI, acl, app.getQueue()); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationACLs.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationACLs.java index fa1106c..5743696 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationACLs.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestApplicationACLs.java @@ -69,6 +69,8 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import javax.servlet.http.HttpServletRequest; + public class TestApplicationACLs { private static final String APP_OWNER = "owner"; @@ -112,7 +114,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( + HttpServletRequest.class))).thenAnswer(new Answer() { public Object answer(InvocationOnMock invocation) { return isQueueUser; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java index f5826c1..113b483 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestClientRMService.java @@ -152,6 +152,8 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import javax.servlet.http.HttpServletRequest; + public class TestClientRMService { private static final Log LOG = LogFactory.getLog(TestClientRMService.class); @@ -474,7 +476,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(HttpServletRequest.class))).thenReturn(true); return new ClientRMService(rmContext, yarnScheduler, appManager, mockAclsManager, mockQueueACLsManager, null); } @@ -575,7 +578,8 @@ 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(HttpServletRequest.class))) + .thenReturn(true); when(mockAclsManager.checkAccess(any(UserGroupInformation.class), any(ApplicationAccessType.class), anyString(), any(ApplicationId.class))).thenReturn(true); @@ -601,7 +605,8 @@ 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(HttpServletRequest.class))) + .thenReturn(false); when(mockAclsManager1.checkAccess(any(UserGroupInformation.class), any(ApplicationAccessType.class), anyString(), any(ApplicationId.class))).thenReturn(false); @@ -640,7 +645,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(HttpServletRequest.class))) + .thenReturn(true); ClientRMService rmService = new ClientRMService(rmContext, yarnScheduler, appManager, mockAclsManager, mockQueueACLsManager, null); @@ -728,7 +734,8 @@ 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(HttpServletRequest.class))) + .thenReturn(true); ClientRMService rmService = new ClientRMService(rmContext, yarnScheduler, appManager, mockAclsManager, mockQueueACLsManager, null);