/** * 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.security; import java.io.IOException; import java.io.File; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Enumeration; import java.net.URI; import junit.framework.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.tools.DFSAdmin; import org.apache.hadoop.io.Text; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.ipc.Server; import org.apache.hadoop.ipc.VersionedProtocol; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.security.authorize.ProxyUsers; import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.TokenInfo; import org.junit.Test; import org.apache.hadoop.ipc.TestSaslRPC; import org.apache.hadoop.ipc.TestSaslRPC.TestTokenSecretManager; import org.apache.hadoop.ipc.TestSaslRPC.TestTokenIdentifier; import org.apache.hadoop.ipc.TestSaslRPC.TestTokenSelector; import org.apache.hadoop.filecache.DistributedCache; import org.apache.commons.logging.*; /** * */ public class TestDistributedCacheAlternateFileSystem { final private static String REAL_USER_NAME = "realUser1@HADOOP.APACHE.ORG"; final private static String REAL_USER_SHORT_NAME = "realUser1"; final private static String PROXY_USER_NAME = "proxyUser"; final private static String GROUP1_NAME = "group1"; final private static String GROUP2_NAME = "group2"; final private static String[] GROUP_NAMES = new String[] { GROUP1_NAME, GROUP2_NAME }; private static final String ADDRESS = "0.0.0.0"; private TestProtocol proxy; private static Configuration masterConf = new Configuration(); final private static String ALTERNATE_FILE_BASE = "gqlpt"; public static final Log LOG = LogFactory .getLog(TestDistributedCacheAlternateFileSystem.class); static { masterConf.set("hadoop.security.auth_to_local", "RULE:[2:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" + "RULE:[1:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" + "DEFAULT"); UserGroupInformation.setConfiguration(masterConf); } private void configureSuperUserIPAddresses(Configuration conf, String superUserShortName) throws IOException { ArrayList<String> ipList = new ArrayList<String>(); Enumeration<NetworkInterface> netInterfaceList = NetworkInterface .getNetworkInterfaces(); while (netInterfaceList.hasMoreElements()) { NetworkInterface inf = netInterfaceList.nextElement(); Enumeration<InetAddress> addrList = inf.getInetAddresses(); while (addrList.hasMoreElements()) { InetAddress addr = addrList.nextElement(); ipList.add(addr.getHostAddress()); } } StringBuilder builder = new StringBuilder(); for (String ip : ipList) { builder.append(ip); builder.append(','); } builder.append("127.0.1.1,"); builder.append(InetAddress.getLocalHost().getCanonicalHostName()); LOG.info("Local Ip addresses: "+builder.toString()); conf.setStrings(ProxyUsers.getProxySuperuserIpConfKey(superUserShortName), builder.toString()); } private FileSystem getFS (UserGroupInformation ugi, final Configuration conf) throws IOException { final Path sysDir = new Path("/" + ALTERNATE_FILE_BASE); // getSystemDir() try { return ugi.doAs(new PrivilegedExceptionAction<FileSystem>() { public FileSystem run() throws IOException { return sysDir.getFileSystem(conf); } }); } catch (InterruptedException e) { throw new RuntimeException(e); } } private void addToClasspath(final FileSystem proxyUserFileSystem, final FileSystem realUserFileSystem, final UserGroupInformation ugi, final String corePathString, final Configuration conf) throws IOException, InterruptedException { ugi.doAs(new PrivilegedExceptionAction<Boolean>() { public Boolean run()throws IOException { DistributedCache.addFileToClassPath (new Path("proxy-fs-as-" + corePathString), conf, proxyUserFileSystem); DistributedCache.addFileToClassPath (new Path("real-fs-as-" + corePathString), conf, realUserFileSystem); DistributedCache.addFileToClassPath (new Path("no-fs-as-" + corePathString), conf); return true; } }); } private static boolean uriUsesProxyFS(URI uri) { String uriString = uri.toString(); return uriString.contains("file:/" + ALTERNATE_FILE_BASE + "/"); } private static boolean uriShouldUseProxyFS(URI uri) { String uriString = uri.toString(); int filenameStart = uriString.lastIndexOf(File.separator) + 1; String fileName = uriString.substring(filenameStart); int lastProxyOccurrence = uriString.lastIndexOf("proxy"); return (fileName.contains("proxy-fs-as") || (fileName.contains("no-fs-as") && fileName.contains("as-proxy"))); } @Test public void testDistributedCacheProxyUsers() throws Exception { // ensure that doAs works correctly UserGroupInformation realUserUgi = UserGroupInformation .createRemoteUser(REAL_USER_NAME); UserGroupInformation proxyUserUgi = UserGroupInformation.createProxyUser( PROXY_USER_NAME, realUserUgi); UserGroupInformation curUGI = proxyUserUgi .doAs(new PrivilegedExceptionAction<UserGroupInformation>() { public UserGroupInformation run() throws IOException { return UserGroupInformation.getCurrentUser(); } }); Assert.assertTrue(curUGI.toString().equals( PROXY_USER_NAME + " via " + REAL_USER_NAME)); final Configuration conf = new Configuration(); final FileSystem realUserFileSystem = getFS(realUserUgi, conf); FileSystem proxyUserFileSystemTemp; String oldWorkingDir = System.getProperty("user.dir"); try { System.setProperty("user.dir", "/" + ALTERNATE_FILE_BASE); proxyUserFileSystemTemp = getFS(proxyUserUgi, conf); } finally { System.setProperty("user.dir", oldWorkingDir); } final FileSystem proxyUserFileSystem = proxyUserFileSystemTemp; addToClasspath(proxyUserFileSystem, realUserFileSystem, realUserUgi, "real.jar", conf); addToClasspath(proxyUserFileSystem, realUserFileSystem, proxyUserUgi, "proxy.jar", conf); URI[] result = DistributedCache.getCacheFiles(conf); for (URI uri : result) { System.out.println("One URI is " + uri); } for (URI uri : result) { Assert.assertEquals("Inconsistent file system usage for URI " + uri, uriUsesProxyFS(uri), uriShouldUseProxyFS(uri)); } } @TokenInfo(TestTokenSelector.class) public interface TestProtocol extends VersionedProtocol { public static final long versionID = 1L; String aMethod() throws IOException; } public class TestImpl implements TestProtocol { public String aMethod() throws IOException { return UserGroupInformation.getCurrentUser().toString(); } public long getProtocolVersion(String protocol, long clientVersion) throws IOException { // TODO Auto-generated method stub return TestProtocol.versionID; } } // private void refreshConf(Configuration conf) throws IOException { ProxyUsers.refreshSuperUserGroupsConfiguration(conf); } }