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.
This commit is contained in:
parent
7b07acb0a5
commit
b4c951ab83
|
@ -862,6 +862,9 @@ Release 2.6.0 - UNRELEASED
|
||||||
YARN-2804. Fixed Timeline service to not fill the logs with JAXB bindings
|
YARN-2804. Fixed Timeline service to not fill the logs with JAXB bindings
|
||||||
exceptions. (Zhijie Shen via vinodkv)
|
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
|
Release 2.5.2 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue