Return-Path: X-Original-To: apmail-hadoop-yarn-commits-archive@minotaur.apache.org Delivered-To: apmail-hadoop-yarn-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 796C7FFB1 for ; Fri, 31 May 2013 04:13:48 +0000 (UTC) Received: (qmail 8491 invoked by uid 500); 31 May 2013 04:13:47 -0000 Delivered-To: apmail-hadoop-yarn-commits-archive@hadoop.apache.org Received: (qmail 8384 invoked by uid 500); 31 May 2013 04:13:47 -0000 Mailing-List: contact yarn-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: yarn-commits@hadoop.apache.org Delivered-To: mailing list yarn-commits@hadoop.apache.org Received: (qmail 8312 invoked by uid 99); 31 May 2013 04:13:45 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 31 May 2013 04:13:45 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 31 May 2013 04:13:41 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id B4A3023889EB; Fri, 31 May 2013 04:13:20 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1488085 [3/3] - in /hadoop/common/trunk/hadoop-yarn-project: ./ hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/ hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/protocolrecords/impl... Date: Fri, 31 May 2013 04:13:18 -0000 To: yarn-commits@hadoop.apache.org From: sseth@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130531041320.B4A3023889EB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java?rev=1488085&r1=1488084&r2=1488085&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java (original) +++ hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/TestContainerManagerSecurity.java Fri May 31 04:13:16 2013 @@ -38,9 +38,7 @@ import org.apache.commons.logging.LogFac import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.fs.UnsupportedFileSystemException; -import org.apache.hadoop.io.DataInputBuffer; import org.apache.hadoop.io.Text; -import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; @@ -49,7 +47,6 @@ import org.apache.hadoop.util.Shell; import org.apache.hadoop.yarn.api.AMRMProtocol; import org.apache.hadoop.yarn.api.ContainerManager; import org.apache.hadoop.yarn.api.protocolrecords.AllocateRequest; -import org.apache.hadoop.yarn.api.protocolrecords.GetContainerStatusRequest; import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationRequest; import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationRequest; import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterRequest; @@ -121,8 +118,8 @@ public class TestContainerManagerSecurit // Testing for malicious user testMaliceUser(); - // Testing for unauthorized user - testUnauthorizedUser(); + // Testing for usage of expired tokens + testExpiredTokens(); } finally { if (yarnCluster != null) { @@ -184,6 +181,15 @@ public class TestContainerManagerSecurit resourceManager.getClientRMService().forceKillApplication(request); } + /** + * This tests a malice user getting a proper token but then messing with it by + * tampering with containerID/Resource etc.. His/her containers should be + * rejected. + * + * @throws IOException + * @throws InterruptedException + * @throws YarnRemoteException + */ private void testMaliceUser() throws IOException, InterruptedException, YarnRemoteException { @@ -205,30 +211,60 @@ public class TestContainerManagerSecurit appID); // Now talk to the NM for launching the container with modified resource - final ContainerId containerID = allocatedContainer.getId(); - UserGroupInformation maliceUser = UserGroupInformation - .createRemoteUser(containerID.toString()); ContainerToken containerToken = allocatedContainer.getContainerToken(); - byte[] identifierBytes = containerToken.getIdentifier().array(); - - DataInputBuffer di = new DataInputBuffer(); - di.reset(identifierBytes, identifierBytes.length); - - ContainerTokenIdentifier dummyIdentifier = new ContainerTokenIdentifier(); - dummyIdentifier.readFields(di); + ContainerTokenIdentifier originalContainerTokenId = + BuilderUtils.newContainerTokenIdentifier(containerToken); // Malice user modifies the resource amount Resource modifiedResource = BuilderUtils.newResource(2048, 1); ContainerTokenIdentifier modifiedIdentifier = - new ContainerTokenIdentifier(dummyIdentifier.getContainerID(), - dummyIdentifier.getNmHostAddress(), "testUser", modifiedResource, - Long.MAX_VALUE, dummyIdentifier.getMasterKeyId(), + new ContainerTokenIdentifier(originalContainerTokenId.getContainerID(), + originalContainerTokenId.getNmHostAddress(), "testUser", + modifiedResource, Long.MAX_VALUE, + originalContainerTokenId.getMasterKeyId(), ResourceManager.clusterTimeStamp); - Token modifiedToken = new Token( - modifiedIdentifier.getBytes(), containerToken.getPassword().array(), - new Text(containerToken.getKind()), new Text(containerToken - .getService())); + Token modifiedToken = + new Token(modifiedIdentifier.getBytes(), + containerToken.getPassword().array(), new Text( + containerToken.getKind()), new Text(containerToken.getService())); + makeTamperedStartContainerCall(yarnRPC, allocatedContainer, + modifiedIdentifier, modifiedToken); + + // Malice user modifies the container-Id + ContainerId newContainerId = + BuilderUtils.newContainerId( + BuilderUtils.newApplicationAttemptId(originalContainerTokenId + .getContainerID().getApplicationAttemptId().getApplicationId(), 1), + originalContainerTokenId.getContainerID().getId() + 42); + modifiedIdentifier = + new ContainerTokenIdentifier(newContainerId, + originalContainerTokenId.getNmHostAddress(), "testUser", + originalContainerTokenId.getResource(), Long.MAX_VALUE, + originalContainerTokenId.getMasterKeyId(), + ResourceManager.clusterTimeStamp); + modifiedToken = + new Token(modifiedIdentifier.getBytes(), + containerToken.getPassword().array(), new Text( + containerToken.getKind()), new Text(containerToken.getService())); + makeTamperedStartContainerCall(yarnRPC, allocatedContainer, + modifiedIdentifier, modifiedToken); + + // Similarly messing with anything else will fail. + + KillApplicationRequest request = Records + .newRecord(KillApplicationRequest.class); + request.setApplicationId(appID); + resourceManager.getClientRMService().forceKillApplication(request); + } + + private void makeTamperedStartContainerCall(final YarnRPC yarnRPC, + final Container allocatedContainer, + final ContainerTokenIdentifier modifiedIdentifier, + Token modifiedToken) { + final ContainerId containerID = allocatedContainer.getId(); + UserGroupInformation maliceUser = UserGroupInformation + .createRemoteUser(containerID.toString()); maliceUser.addToken(modifiedToken); maliceUser.doAs(new PrivilegedAction() { @Override @@ -239,11 +275,14 @@ public class TestContainerManagerSecurit conf); LOG.info("Going to contact NM: ilLegal request"); - GetContainerStatusRequest request = recordFactory - .newRecordInstance(GetContainerStatusRequest.class); - request.setContainerId(containerID); + StartContainerRequest request = + Records.newRecord(StartContainerRequest.class); try { - client.getContainerStatus(request); + request.setContainerToken(allocatedContainer.getContainerToken()); + ContainerLaunchContext context = + createContainerLaunchContextForTest(modifiedIdentifier); + request.setContainerLaunchContext(context); + client.startContainer(request); fail("Connection initiation with illegally modified " + "tokens is expected to fail."); } catch (YarnRemoteException e) { @@ -263,14 +302,9 @@ public class TestContainerManagerSecurit return null; } }); - - KillApplicationRequest request = Records - .newRecord(KillApplicationRequest.class); - request.setApplicationId(appID); - resourceManager.getClientRMService().forceKillApplication(request); } - private void testUnauthorizedUser() throws IOException, InterruptedException, + private void testExpiredTokens() throws IOException, InterruptedException, YarnRemoteException { LOG.info("\n\nRunning test for malice user"); @@ -293,48 +327,12 @@ public class TestContainerManagerSecurit // Now talk to the NM for launching the container with modified containerID final ContainerId containerID = allocatedContainer.getId(); - /////////// Test calls with illegal containerIDs and illegal Resources - UserGroupInformation unauthorizedUser = UserGroupInformation - .createRemoteUser(containerID.toString()); ContainerToken containerToken = allocatedContainer.getContainerToken(); - - byte[] identifierBytes = containerToken.getIdentifier().array(); - DataInputBuffer di = new DataInputBuffer(); - di.reset(identifierBytes, identifierBytes.length); - final ContainerTokenIdentifier tokenId = new ContainerTokenIdentifier(); - tokenId.readFields(di); - - Token token = new Token( - identifierBytes, containerToken.getPassword().array(), new Text( - containerToken.getKind()), new Text(containerToken.getService())); - - unauthorizedUser.addToken(token); - ContainerManager client = - unauthorizedUser.doAs(new PrivilegedAction() { - @Override - public ContainerManager run() { - ContainerManager client = (ContainerManager) yarnRPC.getProxy( - ContainerManager.class, NetUtils - .createSocketAddr(allocatedContainer.getNodeId().toString()), - conf); - - LOG.info("Going to contact NM: unauthorized request"); - - callWithIllegalContainerID(client, tokenId, allocatedContainer); - callWithIllegalResource(client, tokenId, allocatedContainer); - // UserName is no longer sent using containerLaunchContext. -// callWithIllegalUserName(client, tokenId, allocatedContainer); - - return client; - } - }); - - // ///////// End of testing for illegal containerIDs, illegal Resources and - // illegal users + final ContainerTokenIdentifier tokenId = + BuilderUtils.newContainerTokenIdentifier(containerToken); /////////// Test calls with expired tokens - RPC.stopProxy(client); - unauthorizedUser = UserGroupInformation + UserGroupInformation unauthorizedUser = UserGroupInformation .createRemoteUser(containerID.toString()); RMContainerTokenSecretManager containerTokenSecreteManager = @@ -349,9 +347,10 @@ public class TestContainerManagerSecurit containerTokenSecreteManager.createPassword( newTokenId); // Create a valid token by using the key from the RM. - token = new Token( - newTokenId.getBytes(), passowrd, new Text( - containerToken.getKind()), new Text(containerToken.getService())); + Token token = + new Token(newTokenId.getBytes(), passowrd, + new Text(containerToken.getKind()), new Text( + containerToken.getService())); unauthorizedUser.addToken(token); unauthorizedUser.doAs(new PrivilegedAction() { @@ -369,7 +368,7 @@ public class TestContainerManagerSecurit request.setContainerLaunchContext(context); allocatedContainer.setContainerToken(BuilderUtils.newContainerToken( allocatedContainer.getNodeId(), passowrd, newTokenId)); - request.setContainer(allocatedContainer); + request.setContainerToken(allocatedContainer.getContainerToken()); //Calling startContainer with an expired token. try { @@ -524,93 +523,6 @@ public class TestContainerManagerSecurit return allocatedContainers.get(0); } - void callWithIllegalContainerID(ContainerManager client, - ContainerTokenIdentifier tokenId, Container container) { - StartContainerRequest request = recordFactory - .newRecordInstance(StartContainerRequest.class); - ContainerLaunchContext context = - createContainerLaunchContextForTest(tokenId); - ContainerId newContainerId = BuilderUtils.newContainerId(BuilderUtils - .newApplicationAttemptId(tokenId.getContainerID() - .getApplicationAttemptId().getApplicationId(), 1), 42); - ContainerId oldContainerId = container.getId(); - try { - container.setId(newContainerId); - request.setContainer(container); - request.setContainerLaunchContext(context); - 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. " - + "\nExpected containerId: " + tokenId.getContainerID() - + " Found: " + newContainerId.toString())); - } catch (IOException e) { - LOG.info("Got IOException: ",e); - fail("IOException is not expected."); - } finally { - container.setId(oldContainerId); - } - } - - void callWithIllegalResource(ContainerManager client, - ContainerTokenIdentifier tokenId, Container container) { - StartContainerRequest request = recordFactory - .newRecordInstance(StartContainerRequest.class); - // Authenticated but unauthorized, due to wrong resource - ContainerLaunchContext context = - createContainerLaunchContextForTest(tokenId); - Resource rsrc = container.getResource(); - container.setResource(BuilderUtils.newResource(2048, 1)); - request.setContainerLaunchContext(context); - request.setContainer(container); - 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( - "\nExpected resource " + tokenId.getResource().toString() - + " but found " + container.getResource().toString())); - } catch (IOException e) { - LOG.info("Got IOException: ",e); - fail("IOException is not expected."); - } - container.setResource(rsrc); - } - - void callWithIllegalUserName(ContainerManager client, - ContainerTokenIdentifier tokenId, Container container) { - StartContainerRequest request = recordFactory - .newRecordInstance(StartContainerRequest.class); - // Authenticated but unauthorized, due to wrong resource - ContainerLaunchContext context = - createContainerLaunchContextForTest(tokenId); - String user = "invalidUser"; - request.setContainerLaunchContext(context); - request.setContainer(container); - 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 " + user)); - } catch (IOException e) { - LOG.info("Got IOException: ",e); - fail("IOException is not expected."); - } - } - private ContainerLaunchContext createContainerLaunchContextForTest( ContainerTokenIdentifier tokenId) { ContainerLaunchContext context =