Переглянути джерело

Fix NodeManager to verify the application's user-name.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1390825 13f79535-47bb-0310-9956-ffa450edef68
Vinod Kumar Vavilapalli 12 роки тому
батько
коміт
40062e1aaa
8 змінених файлів з 68 додано та 25 видалено
  1. 9 1
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ContainerTokenIdentifier.java
  2. 8 5
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/BaseContainerTokenSecretManager.java
  3. 9 2
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/ContainerManagerImpl.java
  4. 6 6
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java
  5. 1 1
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java
  6. 1 1
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AppSchedulable.java
  7. 2 1
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fifo/FifoScheduler.java
  8. 32 8
      hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java

+ 9 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/security/ContainerTokenIdentifier.java

@@ -48,14 +48,16 @@ public class ContainerTokenIdentifier extends TokenIdentifier {
 
   private ContainerId containerId;
   private String nmHostAddr;
+  private String appSubmitter;
   private Resource resource;
   private long expiryTimeStamp;
   private int masterKeyId;
 
   public ContainerTokenIdentifier(ContainerId containerID, String hostName,
-      Resource r, long expiryTimeStamp, int masterKeyId) {
+      String appSubmitter, Resource r, long expiryTimeStamp, int masterKeyId) {
     this.containerId = containerID;
     this.nmHostAddr = hostName;
+    this.appSubmitter = appSubmitter;
     this.resource = r;
     this.expiryTimeStamp = expiryTimeStamp;
     this.masterKeyId = masterKeyId;
@@ -71,6 +73,10 @@ public class ContainerTokenIdentifier extends TokenIdentifier {
     return this.containerId;
   }
 
+  public String getApplicationSubmitter() {
+    return this.appSubmitter;
+  }
+
   public String getNmHostAddress() {
     return this.nmHostAddr;
   }
@@ -98,6 +104,7 @@ public class ContainerTokenIdentifier extends TokenIdentifier {
     out.writeInt(applicationAttemptId.getAttemptId());
     out.writeInt(this.containerId.getId());
     out.writeUTF(this.nmHostAddr);
+    out.writeUTF(this.appSubmitter);
     out.writeInt(this.resource.getMemory());
     out.writeLong(this.expiryTimeStamp);
     out.writeInt(this.masterKeyId);
@@ -112,6 +119,7 @@ public class ContainerTokenIdentifier extends TokenIdentifier {
     this.containerId = BuilderUtils.newContainerId(applicationAttemptId, in
         .readInt());
     this.nmHostAddr = in.readUTF();
+    this.appSubmitter = in.readUTF();
     this.resource = BuilderUtils.newResource(in.readInt());
     this.expiryTimeStamp = in.readLong();
     this.masterKeyId = in.readInt();

+ 8 - 5
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/security/BaseContainerTokenSecretManager.java

@@ -128,7 +128,8 @@ public class BaseContainerTokenSecretManager extends
   public byte[] createPassword(ContainerTokenIdentifier identifier) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Creating password for " + identifier.getContainerID()
-          + " to be run on NM " + identifier.getNmHostAddress());
+          + " for user " + identifier.getUser() + " to be run on NM "
+          + identifier.getNmHostAddress());
     }
     this.readLock.lock();
     try {
@@ -155,7 +156,8 @@ public class BaseContainerTokenSecretManager extends
       throws org.apache.hadoop.security.token.SecretManager.InvalidToken {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Retrieving password for " + identifier.getContainerID()
-          + " to be run on NM " + identifier.getNmHostAddress());
+          + " for user " + identifier.getUser() + " to be run on NM "
+          + identifier.getNmHostAddress());
     }
     return createPassword(identifier.getBytes(), masterKey.getSecretKey());
   }
@@ -173,11 +175,12 @@ public class BaseContainerTokenSecretManager extends
    * 
    * @param containerId
    * @param nodeId
+   * @param appSubmitter
    * @param capability
    * @return the container-token
    */
   public ContainerToken createContainerToken(ContainerId containerId,
-      NodeId nodeId, Resource capability) {
+      NodeId nodeId, String appSubmitter, Resource capability) {
     byte[] password;
     ContainerTokenIdentifier tokenIdentifier;
     long expiryTimeStamp =
@@ -188,8 +191,8 @@ public class BaseContainerTokenSecretManager extends
     try {
       tokenIdentifier =
           new ContainerTokenIdentifier(containerId, nodeId.toString(),
-            capability, expiryTimeStamp, this.currentMasterKey.getMasterKey()
-              .getKeyId());
+            appSubmitter, capability, expiryTimeStamp, this.currentMasterKey
+              .getMasterKey().getKeyId());
       password = this.createPassword(tokenIdentifier);
 
     } finally {

+ 9 - 2
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/ContainerManagerImpl.java

@@ -329,7 +329,6 @@ public class ContainerManagerImpl extends CompositeService implements
             + remoteUgi.getTokenIdentifiers().size());
       }
 
-
       // Get the tokenId from the remote user ugi
       ContainerTokenIdentifier tokenId =
           selectContainerTokenIdentifier(remoteUgi);
@@ -341,8 +340,16 @@ public class ContainerManagerImpl extends CompositeService implements
                 + containerIDStr);
       } else {
 
+        // Is the container coming in with correct user-name?
+        if (!tokenId.getApplicationSubmitter().equals(launchContext.getUser())) {
+          unauthorized = true;
+          messageBuilder.append("\n Expected user-name "
+              + tokenId.getApplicationSubmitter() + " but found "
+              + launchContext.getUser());
+        }
+
         // Is the container being relaunched? Or RPC layer let startCall with 
-    	//  tokens generated off old-secret through 
+      	//  tokens generated off old-secret through?
         if (!this.context.getContainerTokenSecretManager()
           .isValidStartContainerRequest(tokenId)) {
           unauthorized = true;

+ 6 - 6
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java

@@ -231,7 +231,6 @@ public class RMAppManager implements EventHandler<RMAppManagerEvent> {
     RMApp application = null;
     try {
       String clientTokenStr = null;
-      String user = UserGroupInformation.getCurrentUser().getShortUserName();
       if (UserGroupInformation.isSecurityEnabled()) {
         Token<ClientTokenIdentifier> clientToken = new 
             Token<ClientTokenIdentifier>(
@@ -256,11 +255,12 @@ public class RMAppManager implements EventHandler<RMAppManagerEvent> {
           submissionContext);
 
       // Create RMApp
-      application = new RMAppImpl(applicationId, rmContext,
-          this.conf, submissionContext.getApplicationName(), user,
-          submissionContext.getQueue(), submissionContext, clientTokenStr,
-          appStore, this.scheduler,
-          this.masterService, submitTime);
+      application =
+          new RMAppImpl(applicationId, rmContext, this.conf,
+            submissionContext.getApplicationName(),
+            submissionContext.getUser(), submissionContext.getQueue(),
+            submissionContext, clientTokenStr, appStore, this.scheduler,
+            this.masterService, submitTime);
 
       // Sanity check - duplicate?
       if (rmContext.getRMApps().putIfAbsent(applicationId, application) != 

+ 1 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/LeafQueue.java

@@ -1197,7 +1197,7 @@ public class LeafQueue implements CSQueue {
     if (UserGroupInformation.isSecurityEnabled()) {
       containerToken =
           containerTokenSecretManager.createContainerToken(containerId, nodeId,
-            capability);
+            application.getUser(), capability);
       if (containerToken == null) {
         return null; // Try again later.
       }

+ 1 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fair/AppSchedulable.java

@@ -161,7 +161,7 @@ public class AppSchedulable extends Schedulable {
     if (UserGroupInformation.isSecurityEnabled()) {
       containerToken =
           containerTokenSecretManager.createContainerToken(containerId, nodeId,
-            capability);
+            application.getUser(), capability);
       if (containerToken == null) {
         return null; // Try again later.
       }

+ 2 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/fifo/FifoScheduler.java

@@ -539,7 +539,8 @@ public class FifoScheduler implements ResourceScheduler, Configurable {
         if (UserGroupInformation.isSecurityEnabled()) {
           containerToken =
               this.rmContext.getContainerTokenSecretManager()
-                .createContainerToken(containerId, nodeId, capability);
+                .createContainerToken(containerId, nodeId,
+                  application.getUser(), capability);
           if (containerToken == null) {
             return i; // Try again later.
           }

+ 32 - 8
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java

@@ -219,9 +219,10 @@ public class TestContainerManagerSecurity {
 
     // Malice user modifies the resource amount
     Resource modifiedResource = BuilderUtils.newResource(2048);
-    ContainerTokenIdentifier modifiedIdentifier = new ContainerTokenIdentifier(
-        dummyIdentifier.getContainerID(), dummyIdentifier.getNmHostAddress(),
-        modifiedResource, Long.MAX_VALUE, dummyIdentifier.getMasterKeyId());
+    ContainerTokenIdentifier modifiedIdentifier =
+        new ContainerTokenIdentifier(dummyIdentifier.getContainerID(),
+          dummyIdentifier.getNmHostAddress(), "testUser", modifiedResource,
+          Long.MAX_VALUE, dummyIdentifier.getMasterKeyId());
     Token<ContainerTokenIdentifier> modifiedToken = new Token<ContainerTokenIdentifier>(
         modifiedIdentifier.getBytes(), containerToken.getPassword().array(),
         new Text(containerToken.getKind()), new Text(containerToken
@@ -320,12 +321,14 @@ public class TestContainerManagerSecurity {
 
         callWithIllegalContainerID(client, tokenId);
         callWithIllegalResource(client, tokenId);
+        callWithIllegalUserName(client, tokenId);
 
         return client;
       }
     });
     
-    /////////// End of testing for illegal containerIDs and illegal Resources
+    // ///////// End of testing for illegal containerIDs, illegal Resources and
+    // illegal users
 
     /////////// Test calls with expired tokens
     RPC.stopProxy(client);
@@ -336,7 +339,7 @@ public class TestContainerManagerSecurity {
       resourceManager.getRMContainerTokenSecretManager(); 
     final ContainerTokenIdentifier newTokenId =
         new ContainerTokenIdentifier(tokenId.getContainerID(),
-          tokenId.getNmHostAddress(), tokenId.getResource(),
+          tokenId.getNmHostAddress(), "testUser", tokenId.getResource(),
           System.currentTimeMillis() - 1, 
           containerTokenSecreteManager.getCurrentKey().getKeyId());
     byte[] passowrd =
@@ -346,9 +349,7 @@ public class TestContainerManagerSecurity {
     token = new Token<ContainerTokenIdentifier>(
         newTokenId.getBytes(), passowrd, new Text(
             containerToken.getKind()), new Text(containerToken.getService()));
-    
-    
-    
+
     unauthorizedUser.addToken(token);
     unauthorizedUser.doAs(new PrivilegedAction<Void>() {
       @Override
@@ -567,6 +568,29 @@ public class TestContainerManagerSecurity {
     }
   }
 
+  void callWithIllegalUserName(ContainerManager client,
+      ContainerTokenIdentifier tokenId) {
+    StartContainerRequest request = recordFactory
+        .newRecordInstance(StartContainerRequest.class);
+    // Authenticated but unauthorized, due to wrong resource
+    ContainerLaunchContext context =
+        createContainerLaunchContextForTest(tokenId);
+    context.setUser("Saruman"); // Set a different user-name.
+    request.setContainerLaunchContext(context);
+    try {
+      client.startContainer(request);
+      fail("Connection initiation with unauthorized "
+          + "access is expected to fail.");
+    } catch (YarnRemoteException e) {
+      LOG.info("Got exception : ", e);
+      Assert.assertTrue(e.getMessage().contains(
+          "Unauthorized request to start container. "));
+      Assert.assertTrue(e.getMessage().contains(
+        "Expected user-name " + tokenId.getApplicationSubmitter()
+            + " but found " + context.getUser()));
+    }
+  }
+
   private ContainerLaunchContext createContainerLaunchContextForTest(
       ContainerTokenIdentifier tokenId) {
     ContainerLaunchContext context =