YARN-2767. Added a test case to verify that http static user cannot kill or submit apps in the secure mode. Contributed by Varun Vasudev.

(cherry picked from commit 7a4c92a9d55fcecef066053ac30dff0fcd4ec90c)
This commit is contained in:
Zhijie Shen 2014-11-05 10:56:39 -08:00
parent 8702cc2360
commit a1764e4d33
2 changed files with 198 additions and 0 deletions

View File

@ -790,6 +790,9 @@ Release 2.6.0 - UNRELEASED
YARN-2804. Fixed Timeline service to not fill the logs with JAXB bindings
exceptions. (Zhijie Shen via vinodkv)
YARN-2767. Added a test case to verify that http static user cannot kill or submit
apps in the secure mode. (Varun Vasudev via zjshen)
Release 2.5.2 - UNRELEASED
INCOMPATIBLE CHANGES

View File

@ -0,0 +1,195 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.yarn.server.resourcemanager.webapp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.minikdc.MiniKdc;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.KerberosTestUtils;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.fifo.FifoScheduler;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ApplicationSubmissionContextInfo;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.sun.jersey.api.client.ClientResponse.Status;
public class TestRMWebServicesHttpStaticUserPermissions {
private static final File testRootDir = new File("target",
TestRMWebServicesHttpStaticUserPermissions.class.getName() + "-root");
private static File spnegoKeytabFile = new File(
KerberosTestUtils.getKeytabFile());
private static String spnegoPrincipal = KerberosTestUtils
.getServerPrincipal();
private static MiniKdc testMiniKDC;
private static MockRM rm;
static class Helper {
String method;
String requestBody;
Helper(String method, String requestBody) {
this.method = method;
this.requestBody = requestBody;
}
}
@BeforeClass
public static void setUp() {
try {
testMiniKDC = new MiniKdc(MiniKdc.createConf(), testRootDir);
setupKDC();
setupAndStartRM();
} catch (Exception e) {
fail("Couldn't create MiniKDC");
}
}
@AfterClass
public static void tearDown() {
if (testMiniKDC != null) {
testMiniKDC.stop();
}
if (rm != null) {
rm.stop();
}
}
public TestRMWebServicesHttpStaticUserPermissions() throws Exception {
super();
}
private static void setupAndStartRM() throws Exception {
Configuration rmconf = new Configuration();
rmconf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS,
YarnConfiguration.DEFAULT_RM_AM_MAX_ATTEMPTS);
rmconf.setClass(YarnConfiguration.RM_SCHEDULER, FifoScheduler.class,
ResourceScheduler.class);
rmconf.setBoolean(YarnConfiguration.YARN_ACL_ENABLE, true);
rmconf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
"kerberos");
rmconf.set("yarn.resourcemanager.principal", spnegoPrincipal);
rmconf.set("yarn.resourcemanager.keytab",
spnegoKeytabFile.getAbsolutePath());
rmconf.setBoolean("mockrm.webapp.enabled", true);
UserGroupInformation.setConfiguration(rmconf);
rm = new MockRM(rmconf);
rm.start();
}
private static void setupKDC() throws Exception {
testMiniKDC.start();
testMiniKDC.createPrincipal(spnegoKeytabFile, "HTTP/localhost", "client",
UserGroupInformation.getLoginUser().getShortUserName(), "client2");
}
// Test that the http static user can't submit or kill apps
// when secure mode is turned on
@Test
public void testWebServiceAccess() throws Exception {
ApplicationSubmissionContextInfo app =
new ApplicationSubmissionContextInfo();
String appid = "application_123_0";
app.setApplicationId(appid);
String submitAppRequestBody =
TestRMWebServicesDelegationTokenAuthentication
.getMarshalledAppInfo(app);
URL url = new URL("http://localhost:8088/ws/v1/cluster/apps");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// we should be access the apps page with the static user
TestRMWebServicesDelegationTokenAuthentication.setupConn(conn, "GET", "",
"");
try {
conn.getInputStream();
assertEquals(Status.OK.getStatusCode(), conn.getResponseCode());
} catch (IOException e) {
fail("Got " + conn.getResponseCode() + " instead of 200 accessing "
+ url.toString());
}
conn.disconnect();
// new-application, submit app and kill should fail with
// forbidden
Map<String, Helper> urlRequestMap = new HashMap<String, Helper>();
String killAppRequestBody =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<appstate>\n" + " <state>KILLED</state>\n" + "</appstate>";
urlRequestMap.put("http://localhost:8088/ws/v1/cluster/apps", new Helper(
"POST", submitAppRequestBody));
urlRequestMap.put(
"http://localhost:8088/ws/v1/cluster/apps/new-application", new Helper(
"POST", ""));
urlRequestMap.put(
"http://localhost:8088/ws/v1/cluster/apps/app_123_1/state", new Helper(
"PUT", killAppRequestBody));
for (Map.Entry<String, Helper> entry : urlRequestMap.entrySet()) {
URL reqURL = new URL(entry.getKey());
conn = (HttpURLConnection) reqURL.openConnection();
String method = entry.getValue().method;
String body = entry.getValue().requestBody;
TestRMWebServicesDelegationTokenAuthentication.setupConn(conn, method,
"application/xml", body);
try {
conn.getInputStream();
fail("Request " + entry.getKey() + "succeeded but should have failed");
} catch (IOException e) {
assertEquals(Status.FORBIDDEN.getStatusCode(), conn.getResponseCode());
InputStream errorStream = conn.getErrorStream();
String error = "";
BufferedReader reader =
new BufferedReader(new InputStreamReader(errorStream, "UTF8"));
for (String line; (line = reader.readLine()) != null;) {
error += line;
}
reader.close();
errorStream.close();
assertEquals(
"The default static user cannot carry out this operation.", error);
}
conn.disconnect();
}
}
}