|
@@ -22,6 +22,8 @@ import java.io.IOException;
|
|
|
import java.net.InetSocketAddress;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.security.PrivilegedAction;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
|
|
@@ -54,22 +56,35 @@ import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
|
import org.apache.hadoop.yarn.util.Records;
|
|
|
import org.junit.Assert;
|
|
|
import org.junit.Test;
|
|
|
+import org.junit.runner.RunWith;
|
|
|
+import org.junit.runners.Parameterized;
|
|
|
+import org.junit.runners.Parameterized.Parameters;
|
|
|
|
|
|
+@RunWith(Parameterized.class)
|
|
|
public class TestAMAuthorization {
|
|
|
|
|
|
private static final Log LOG = LogFactory.getLog(TestAMAuthorization.class);
|
|
|
|
|
|
- private static final Configuration confWithSecurityEnabled =
|
|
|
- new Configuration();
|
|
|
- static {
|
|
|
- confWithSecurityEnabled.set(
|
|
|
- CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
|
|
|
- UserGroupInformation.setConfiguration(confWithSecurityEnabled);
|
|
|
+ private final Configuration conf;
|
|
|
+
|
|
|
+ @Parameters
|
|
|
+ public static Collection<Object[]> configs() {
|
|
|
+ Configuration conf = new Configuration();
|
|
|
+ Configuration confWithSecurity = new Configuration();
|
|
|
+ confWithSecurity.set(
|
|
|
+ CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
|
|
|
+ UserGroupInformation.AuthenticationMethod.KERBEROS.toString());
|
|
|
+ return Arrays.asList(new Object[][] {{ conf }, { confWithSecurity} });
|
|
|
+ }
|
|
|
+
|
|
|
+ public TestAMAuthorization(Configuration conf) {
|
|
|
+ this.conf = conf;
|
|
|
+ UserGroupInformation.setConfiguration(conf);
|
|
|
}
|
|
|
|
|
|
public static final class MyContainerManager implements ContainerManagementProtocol {
|
|
|
|
|
|
- public ByteBuffer amTokens;
|
|
|
+ public ByteBuffer containerTokens;
|
|
|
|
|
|
public MyContainerManager() {
|
|
|
}
|
|
@@ -78,23 +93,30 @@ public class TestAMAuthorization {
|
|
|
public StartContainerResponse
|
|
|
startContainer(StartContainerRequest request)
|
|
|
throws YarnException {
|
|
|
- amTokens = request.getContainerLaunchContext().getTokens();
|
|
|
+ containerTokens = request.getContainerLaunchContext().getTokens();
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public StopContainerResponse stopContainer(StopContainerRequest request)
|
|
|
throws YarnException {
|
|
|
- // TODO Auto-generated method stub
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public GetContainerStatusResponse getContainerStatus(
|
|
|
GetContainerStatusRequest request) throws YarnException {
|
|
|
- // TODO Auto-generated method stub
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ public Credentials getContainerCredentials() throws IOException {
|
|
|
+ Credentials credentials = new Credentials();
|
|
|
+ DataInputByteBuffer buf = new DataInputByteBuffer();
|
|
|
+ containerTokens.rewind();
|
|
|
+ buf.reset(containerTokens);
|
|
|
+ credentials.readTokenStorageStream(buf);
|
|
|
+ return credentials;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public static class MockRMWithAMS extends MockRMWithCustomAMLauncher {
|
|
@@ -118,7 +140,7 @@ public class TestAMAuthorization {
|
|
|
public void testAuthorizedAccess() throws Exception {
|
|
|
MyContainerManager containerManager = new MyContainerManager();
|
|
|
final MockRM rm =
|
|
|
- new MockRMWithAMS(confWithSecurityEnabled, containerManager);
|
|
|
+ new MockRMWithAMS(conf, containerManager);
|
|
|
rm.start();
|
|
|
|
|
|
MockNM nm1 = rm.registerNode("localhost:1234", 5120);
|
|
@@ -131,11 +153,11 @@ public class TestAMAuthorization {
|
|
|
nm1.nodeHeartbeat(true);
|
|
|
|
|
|
int waitCount = 0;
|
|
|
- while (containerManager.amTokens == null && waitCount++ < 20) {
|
|
|
+ while (containerManager.containerTokens == null && waitCount++ < 20) {
|
|
|
LOG.info("Waiting for AM Launch to happen..");
|
|
|
Thread.sleep(1000);
|
|
|
}
|
|
|
- Assert.assertNotNull(containerManager.amTokens);
|
|
|
+ Assert.assertNotNull(containerManager.containerTokens);
|
|
|
|
|
|
RMAppAttempt attempt = app.getCurrentAppAttempt();
|
|
|
ApplicationAttemptId applicationAttemptId = attempt.getAppAttemptId();
|
|
@@ -147,11 +169,7 @@ public class TestAMAuthorization {
|
|
|
|
|
|
UserGroupInformation currentUser = UserGroupInformation
|
|
|
.createRemoteUser(applicationAttemptId.toString());
|
|
|
- Credentials credentials = new Credentials();
|
|
|
- DataInputByteBuffer buf = new DataInputByteBuffer();
|
|
|
- containerManager.amTokens.rewind();
|
|
|
- buf.reset(containerManager.amTokens);
|
|
|
- credentials.readTokenStorageStream(buf);
|
|
|
+ Credentials credentials = containerManager.getContainerCredentials();
|
|
|
currentUser.addCredentials(credentials);
|
|
|
|
|
|
ApplicationMasterProtocol client = currentUser
|
|
@@ -169,8 +187,10 @@ public class TestAMAuthorization {
|
|
|
RegisterApplicationMasterResponse response =
|
|
|
client.registerApplicationMaster(request);
|
|
|
Assert.assertNotNull(response.getClientToAMTokenMasterKey());
|
|
|
- Assert
|
|
|
+ if (UserGroupInformation.isSecurityEnabled()) {
|
|
|
+ Assert
|
|
|
.assertTrue(response.getClientToAMTokenMasterKey().array().length > 0);
|
|
|
+ }
|
|
|
Assert.assertEquals("Register response has bad ACLs", "*",
|
|
|
response.getApplicationACLs().get(ApplicationAccessType.VIEW_APP));
|
|
|
|
|
@@ -180,7 +200,7 @@ public class TestAMAuthorization {
|
|
|
@Test
|
|
|
public void testUnauthorizedAccess() throws Exception {
|
|
|
MyContainerManager containerManager = new MyContainerManager();
|
|
|
- MockRM rm = new MockRMWithAMS(confWithSecurityEnabled, containerManager);
|
|
|
+ MockRM rm = new MockRMWithAMS(conf, containerManager);
|
|
|
rm.start();
|
|
|
|
|
|
MockNM nm1 = rm.registerNode("localhost:1234", 5120);
|
|
@@ -190,11 +210,11 @@ public class TestAMAuthorization {
|
|
|
nm1.nodeHeartbeat(true);
|
|
|
|
|
|
int waitCount = 0;
|
|
|
- while (containerManager.amTokens == null && waitCount++ < 40) {
|
|
|
+ while (containerManager.containerTokens == null && waitCount++ < 40) {
|
|
|
LOG.info("Waiting for AM Launch to happen..");
|
|
|
Thread.sleep(1000);
|
|
|
}
|
|
|
- Assert.assertNotNull(containerManager.amTokens);
|
|
|
+ Assert.assertNotNull(containerManager.containerTokens);
|
|
|
|
|
|
RMAppAttempt attempt = app.getCurrentAppAttempt();
|
|
|
ApplicationAttemptId applicationAttemptId = attempt.getAppAttemptId();
|
|
@@ -229,17 +249,19 @@ public class TestAMAuthorization {
|
|
|
} catch (Exception e) {
|
|
|
// Because there are no tokens, the request should be rejected as the
|
|
|
// server side will assume we are trying simple auth.
|
|
|
+ String availableAuthMethods;
|
|
|
+ if (UserGroupInformation.isSecurityEnabled()) {
|
|
|
+ availableAuthMethods = "[TOKEN, KERBEROS]";
|
|
|
+ } else {
|
|
|
+ availableAuthMethods = "[TOKEN]";
|
|
|
+ }
|
|
|
Assert.assertTrue(e.getCause().getMessage().contains(
|
|
|
"SIMPLE authentication is not enabled. "
|
|
|
- + "Available:[TOKEN, KERBEROS]"));
|
|
|
+ + "Available:" + availableAuthMethods));
|
|
|
}
|
|
|
|
|
|
// Now try to validate invalid authorization.
|
|
|
- Credentials credentials = new Credentials();
|
|
|
- DataInputByteBuffer buf = new DataInputByteBuffer();
|
|
|
- containerManager.amTokens.rewind();
|
|
|
- buf.reset(containerManager.amTokens);
|
|
|
- credentials.readTokenStorageStream(buf);
|
|
|
+ Credentials credentials = containerManager.getContainerCredentials();
|
|
|
currentUser.addCredentials(credentials);
|
|
|
|
|
|
// Create a client to the RM.
|
|
@@ -252,7 +274,8 @@ public class TestAMAuthorization {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- request = Records.newRecord(RegisterApplicationMasterRequest.class);
|
|
|
+ request =
|
|
|
+ Records.newRecord(RegisterApplicationMasterRequest.class);
|
|
|
ApplicationAttemptId otherAppAttemptId = BuilderUtils
|
|
|
.newApplicationAttemptId(applicationAttemptId.getApplicationId(), 42);
|
|
|
request.setApplicationAttemptId(otherAppAttemptId);
|