blob: 61a5e8923b42a30d8e2761023a61b75106592011 [file] [log] [blame]
/**
* 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.router.secure;
import org.apache.commons.lang3.StringUtils;
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.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.server.federation.store.records.SubClusterId;
import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
import org.apache.hadoop.yarn.server.resourcemanager.TestRMRestart;
import org.apache.hadoop.yarn.server.router.Router;
import org.apache.hadoop.yarn.server.router.clientrm.FederationClientInterceptor;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
public abstract class AbstractSecureRouterTest {
private static final Logger LOG = LoggerFactory.getLogger(AbstractSecureRouterTest.class);
////////////////////////////////
// Kerberos Constants
////////////////////////////////
public static final String REALM = "EXAMPLE.COM";
public static final String ROUTER = "router";
public static final String LOCALHOST = "localhost";
public static final String IP127001 = "127.0.0.1";
public static final String ROUTER_LOCALHOST = "router/" + LOCALHOST;
public static final String ROUTER_127001 = "router/" + IP127001;
public static final String ROUTER_REALM = "router@" + REALM;
public static final String ROUTER_LOCALHOST_REALM = ROUTER_LOCALHOST + "@" + REALM;
public static final String SUN_SECURITY_KRB5_DEBUG = "sun.security.krb5.debug";
public static final String KERBEROS = "kerberos";
////////////////////////////////
// BeforeSecureRouterTestClass Init
////////////////////////////////
private static MiniKdc kdc;
private static File routerKeytab;
private static File kdcWorkDir;
private static Configuration conf;
////////////////////////////////
// Specific Constant
// Like Mem, VCore, ClusterNum
////////////////////////////////
private static final int NUM_SUBCLUSTER = 4;
private static final int GB = 1024;
private static final int NM_MEMORY = 8 * GB;
private static final int NM_VCORE = 4;
////////////////////////////////
// Test use in subclasses
////////////////////////////////
private Router router = null;
private static ConcurrentHashMap<SubClusterId, MockRM> mockRMs =
new ConcurrentHashMap<>();
@BeforeClass
public static void beforeSecureRouterTestClass() throws Exception {
// Sets up the KDC and Principals.
setupKDCAndPrincipals();
// Init YarnConfiguration
conf = new YarnConfiguration();
// Enable Kerberos authentication configuration
conf.setBoolean(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, true);
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, KERBEROS);
// Router configuration
conf.set(YarnConfiguration.ROUTER_BIND_HOST, "0.0.0.0");
conf.set(YarnConfiguration.ROUTER_CLIENTRM_INTERCEPTOR_CLASS_PIPELINE,
FederationClientInterceptor.class.getName());
// Router Kerberos KeyTab configuration
conf.set(YarnConfiguration.ROUTER_PRINCIPAL, ROUTER_LOCALHOST_REALM);
conf.set(YarnConfiguration.ROUTER_KEYTAB, routerKeytab.getAbsolutePath());
}
/**
* Sets up the KDC and Principals.
*
* @throws Exception an error occurred.
*/
public static void setupKDCAndPrincipals() throws Exception {
// set up the KDC
File target = new File(System.getProperty("test.dir", "target"));
kdcWorkDir = new File(target, "kdc");
kdcWorkDir.mkdirs();
if (!kdcWorkDir.mkdirs()) {
assertTrue(kdcWorkDir.isDirectory());
}
Properties kdcConf = MiniKdc.createConf();
kdcConf.setProperty(MiniKdc.DEBUG, "true");
kdc = new MiniKdc(kdcConf, kdcWorkDir);
kdc.start();
routerKeytab = createKeytab(ROUTER, "router.keytab");
}
/**
* Initialize RM in safe mode.
*
* @throws Exception an error occurred.
*/
public static void setupSecureMockRM() throws Exception {
for (int i = 0; i < NUM_SUBCLUSTER; i++) {
SubClusterId sc = SubClusterId.newInstance(i);
if (mockRMs.containsKey(sc)) {
continue;
}
MockRM mockRM = new TestRMRestart.TestSecurityMockRM(conf);
mockRM.start();
mockRM.registerNode("127.0.0.1:1234", NM_MEMORY, NM_VCORE);
mockRMs.put(sc, mockRM);
}
}
/**
* Create the keytab for the given principal, includes
* raw principal and $principal/localhost.
*
* @param principal principal short name.
* @param filename filename of keytab.
* @return file of keytab.
* @throws Exception an error occurred.
*/
public static File createKeytab(String principal, String filename) throws Exception {
assertTrue("empty principal", StringUtils.isNotBlank(principal));
assertTrue("empty host", StringUtils.isNotBlank(filename));
assertNotNull("null KDC", kdc);
File keytab = new File(kdcWorkDir, filename);
kdc.createPrincipal(keytab,
principal,
principal + "/localhost",
principal + "/127.0.0.1");
return keytab;
}
/**
* Start the router in safe mode.
*
* @throws Exception an error occurred.
*/
public synchronized void startSecureRouter() {
assertNull("Router is already running", router);
UserGroupInformation.setConfiguration(conf);
router = new Router();
router.init(conf);
router.start();
}
/**
* Shut down the KDC service.
*
* @throws Exception an error occurred.
*/
public static void teardownKDC() throws Exception {
if (kdc != null) {
kdc.stop();
kdc = null;
}
}
/**
* Stop the router in safe mode.
*
* @throws Exception an error occurred.
*/
protected synchronized void stopSecureRouter() throws Exception {
if (router != null) {
router.stop();
router = null;
}
}
/**
* Stop the entire test service.
*
* @throws Exception an error occurred.
*/
@AfterClass
public static void afterSecureRouterTest() throws Exception {
LOG.info("teardown of kdc instance.");
teardownKDC();
}
public static MiniKdc getKdc() {
return kdc;
}
public Router getRouter() {
return router;
}
public static ConcurrentHashMap<SubClusterId, MockRM> getMockRMs() {
return mockRMs;
}
}