HADOOP-7808. Port HADOOP-7510 - Add configurable option to use original hostname in token instead of IP to allow server IP change. Contributed by Daryn Sharp.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1227737 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
03d46dc571
commit
4bb572d336
@ -79,11 +79,19 @@ Trunk (unreleased changes)
|
||||
|
||||
HADOOP-7899. Generate proto java files as part of the build. (tucu)
|
||||
|
||||
HADOOP-7574. Improve FSShell -stat, add user/group elements (XieXianshan via harsh)
|
||||
HADOOP-7574. Improve FSShell -stat, add user/group elements.
|
||||
(XieXianshan via harsh)
|
||||
|
||||
HADOOP-7348. Change 'addnl' in getmerge util to be a flag '-nl' instead (XieXianshan via harsh)
|
||||
HADOOP-7348. Change 'addnl' in getmerge util to be a flag '-nl' instead.
|
||||
(XieXianshan via harsh)
|
||||
|
||||
HADOOP-7919. Remove the unused hadoop.logfile.* properties from the
|
||||
core-default.xml file. (harsh)
|
||||
|
||||
HADOOP-7808. Port HADOOP-7510 - Add configurable option to use original
|
||||
hostname in token instead of IP to allow server IP change.
|
||||
(Daryn Sharp via suresh)
|
||||
|
||||
HADOOP-7919. Remove the unused hadoop.logfile.* properties from the core-default.xml file. (harsh)
|
||||
|
||||
BUGS
|
||||
|
||||
|
@ -114,5 +114,11 @@ public class CommonConfigurationKeys extends CommonConfigurationKeysPublic {
|
||||
public static final String
|
||||
HADOOP_SECURITY_SERVICE_AUTHORIZATION_REFRESH_USER_MAPPINGS =
|
||||
"security.refresh.user.mappings.protocol.acl";
|
||||
|
||||
public static final String HADOOP_SECURITY_TOKEN_SERVICE_USE_IP =
|
||||
"hadoop.security.token.service.use_ip";
|
||||
public static final boolean HADOOP_SECURITY_TOKEN_SERVICE_USE_IP_DEFAULT =
|
||||
true;
|
||||
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
import org.apache.hadoop.fs.Options.Rename;
|
||||
import org.apache.hadoop.fs.permission.FsPermission;
|
||||
import org.apache.hadoop.io.MultipleIOException;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.Credentials;
|
||||
import org.apache.hadoop.security.SecurityUtil;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
@ -186,6 +187,15 @@ public void initialize(URI name, Configuration conf) throws IOException {
|
||||
/** Returns a URI whose scheme and authority identify this FileSystem.*/
|
||||
public abstract URI getUri();
|
||||
|
||||
/**
|
||||
* Resolve the uri's hostname and add the default port if not in the uri
|
||||
* @return URI
|
||||
* @see NetUtils#getCanonicalUri(URI, int)
|
||||
*/
|
||||
protected URI getCanonicalUri() {
|
||||
return NetUtils.getCanonicalUri(getUri(), getDefaultPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default port for this file system.
|
||||
* @return the default port or 0 if there isn't one
|
||||
@ -195,8 +205,13 @@ protected int getDefaultPort() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a canonical name for this file system.
|
||||
* @return a URI string that uniquely identifies this file system
|
||||
* Get a canonical service name for this file system. The token cache is
|
||||
* the only user of this value, and uses it to lookup this filesystem's
|
||||
* service tokens. The token cache will not attempt to acquire tokens if the
|
||||
* service is null.
|
||||
* @return a service string that uniquely identifies this file system, null
|
||||
* if the filesystem does not implement tokens
|
||||
* @see SecurityUtil#buildDTServiceName(URI, int)
|
||||
*/
|
||||
public String getCanonicalServiceName() {
|
||||
return SecurityUtil.buildDTServiceName(getUri(), getDefaultPort());
|
||||
@ -487,32 +502,31 @@ protected FileSystem() {
|
||||
*/
|
||||
protected void checkPath(Path path) {
|
||||
URI uri = path.toUri();
|
||||
if (uri.getScheme() == null) // fs is relative
|
||||
return;
|
||||
String thisScheme = this.getUri().getScheme();
|
||||
String thatScheme = uri.getScheme();
|
||||
String thisAuthority = this.getUri().getAuthority();
|
||||
String thatAuthority = uri.getAuthority();
|
||||
if (thatScheme == null) // fs is relative
|
||||
return;
|
||||
URI thisUri = getCanonicalUri();
|
||||
String thisScheme = thisUri.getScheme();
|
||||
//authority and scheme are not case sensitive
|
||||
if (thisScheme.equalsIgnoreCase(thatScheme)) {// schemes match
|
||||
if (thisAuthority == thatAuthority || // & authorities match
|
||||
(thisAuthority != null &&
|
||||
thisAuthority.equalsIgnoreCase(thatAuthority)))
|
||||
return;
|
||||
|
||||
String thisAuthority = thisUri.getAuthority();
|
||||
String thatAuthority = uri.getAuthority();
|
||||
if (thatAuthority == null && // path's authority is null
|
||||
thisAuthority != null) { // fs has an authority
|
||||
URI defaultUri = getDefaultUri(getConf()); // & is the conf default
|
||||
if (thisScheme.equalsIgnoreCase(defaultUri.getScheme()) &&
|
||||
thisAuthority.equalsIgnoreCase(defaultUri.getAuthority()))
|
||||
return;
|
||||
try { // or the default fs's uri
|
||||
defaultUri = get(getConf()).getUri();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
URI defaultUri = getDefaultUri(getConf());
|
||||
if (thisScheme.equalsIgnoreCase(defaultUri.getScheme())) {
|
||||
uri = defaultUri; // schemes match, so use this uri instead
|
||||
} else {
|
||||
uri = null; // can't determine auth of the path
|
||||
}
|
||||
if (thisScheme.equalsIgnoreCase(defaultUri.getScheme()) &&
|
||||
thisAuthority.equalsIgnoreCase(defaultUri.getAuthority()))
|
||||
}
|
||||
if (uri != null) {
|
||||
// canonicalize uri before comparing with this fs
|
||||
uri = NetUtils.getCanonicalUri(uri, getDefaultPort());
|
||||
thatAuthority = uri.getAuthority();
|
||||
if (thisAuthority == thatAuthority || // authorities match
|
||||
(thisAuthority != null &&
|
||||
thisAuthority.equalsIgnoreCase(thatAuthority)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,15 @@ public URI getUri() {
|
||||
return fs.getUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a qualified URI whose scheme and authority identify this
|
||||
* FileSystem.
|
||||
*/
|
||||
@Override
|
||||
protected URI getCanonicalUri() {
|
||||
return fs.getCanonicalUri();
|
||||
}
|
||||
|
||||
/** Make sure that a path specifies a FileSystem. */
|
||||
public Path makeQualified(Path path) {
|
||||
return fs.makeQualified(path);
|
||||
|
@ -422,7 +422,7 @@ private synchronized boolean setupSaslConnection(final InputStream in2,
|
||||
*/
|
||||
private synchronized boolean updateAddress() throws IOException {
|
||||
// Do a fresh lookup with the old host name.
|
||||
InetSocketAddress currentAddr = new InetSocketAddress(
|
||||
InetSocketAddress currentAddr = NetUtils.createSocketAddrForHost(
|
||||
server.getHostName(), server.getPort());
|
||||
|
||||
if (!server.equals(currentAddr)) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
|
||||
/**
|
||||
* Static utility methods
|
||||
@ -56,14 +57,7 @@ public static List<InetSocketAddress> parse(String specs, int defaultPort) {
|
||||
else {
|
||||
String[] specStrings = specs.split("[ ,]+");
|
||||
for (String specString : specStrings) {
|
||||
int colon = specString.indexOf(':');
|
||||
if (colon < 0 || colon == specString.length() - 1) {
|
||||
result.add(new InetSocketAddress(specString, defaultPort));
|
||||
} else {
|
||||
String hostname = specString.substring(0, colon);
|
||||
int port = Integer.parseInt(specString.substring(colon+1));
|
||||
result.add(new InetSocketAddress(hostname, port));
|
||||
}
|
||||
result.add(NetUtils.createSocketAddr(specString, defaultPort));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
|
||||
/**
|
||||
* Helpers to handle server addresses
|
||||
@ -57,14 +58,7 @@ public static List<InetSocketAddress> parse(String specs, int defaultPort) {
|
||||
else {
|
||||
String[] specStrings = specs.split("[ ,]+");
|
||||
for (String specString : specStrings) {
|
||||
int colon = specString.indexOf(':');
|
||||
if (colon < 0 || colon == specString.length() - 1) {
|
||||
result.add(new InetSocketAddress(specString, defaultPort));
|
||||
} else {
|
||||
String hostname = specString.substring(0, colon);
|
||||
int port = Integer.parseInt(specString.substring(colon+1));
|
||||
result.add(new InetSocketAddress(hostname, port));
|
||||
}
|
||||
result.add(NetUtils.createSocketAddr(specString, defaultPort));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -37,6 +37,7 @@
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
@ -45,11 +46,17 @@
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.ipc.Server;
|
||||
import org.apache.hadoop.ipc.VersionedProtocol;
|
||||
import org.apache.hadoop.security.SecurityUtil;
|
||||
import org.apache.hadoop.util.ReflectionUtils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
//this will need to be replaced someday when there is a suitable replacement
|
||||
import sun.net.dns.ResolverConfiguration;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
|
||||
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
|
||||
@InterfaceStability.Unstable
|
||||
public class NetUtils {
|
||||
@ -65,6 +72,26 @@ public class NetUtils {
|
||||
/** Base URL of the Hadoop Wiki: {@value} */
|
||||
public static final String HADOOP_WIKI = "http://wiki.apache.org/hadoop/";
|
||||
|
||||
private static HostResolver hostResolver;
|
||||
|
||||
static {
|
||||
// SecurityUtils requires a more secure host resolver if tokens are
|
||||
// using hostnames
|
||||
setUseQualifiedHostResolver(!SecurityUtil.getTokenServiceUseIp());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is intended for use only by SecurityUtils!
|
||||
* @param flag where the qualified or standard host resolver is used
|
||||
* to create socket addresses
|
||||
*/
|
||||
@InterfaceAudience.Private
|
||||
public static void setUseQualifiedHostResolver(boolean flag) {
|
||||
hostResolver = flag
|
||||
? new QualifiedHostResolver()
|
||||
: new StandardHostResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the socket factory for the given class according to its
|
||||
* configuration parameter
|
||||
@ -178,43 +205,256 @@ public static InetSocketAddress createSocketAddr(String target,
|
||||
throw new IllegalArgumentException("Target address cannot be null." +
|
||||
helpText);
|
||||
}
|
||||
int colonIndex = target.indexOf(':');
|
||||
if (colonIndex < 0 && defaultPort == -1) {
|
||||
throw new RuntimeException("Not a host:port pair: " + target +
|
||||
helpText);
|
||||
}
|
||||
String hostname;
|
||||
int port = -1;
|
||||
if (!target.contains("/")) {
|
||||
if (colonIndex == -1) {
|
||||
hostname = target;
|
||||
} else {
|
||||
// must be the old style <host>:<port>
|
||||
hostname = target.substring(0, colonIndex);
|
||||
String portStr = target.substring(colonIndex + 1);
|
||||
boolean hasScheme = target.contains("://");
|
||||
URI uri = null;
|
||||
try {
|
||||
port = Integer.parseInt(portStr);
|
||||
} catch (NumberFormatException nfe) {
|
||||
uri = hasScheme ? URI.create(target) : URI.create("dummyscheme://"+target);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't parse port '" + portStr + "'"
|
||||
+ helpText);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// a new uri
|
||||
URI addr = new Path(target).toUri();
|
||||
hostname = addr.getHost();
|
||||
port = addr.getPort();
|
||||
"Does not contain a valid host:port authority: " + target + helpText
|
||||
);
|
||||
}
|
||||
|
||||
String host = uri.getHost();
|
||||
int port = uri.getPort();
|
||||
if (port == -1) {
|
||||
port = defaultPort;
|
||||
}
|
||||
String path = uri.getPath();
|
||||
|
||||
if (getStaticResolution(hostname) != null) {
|
||||
hostname = getStaticResolution(hostname);
|
||||
if ((host == null) || (port < 0) ||
|
||||
(!hasScheme && path != null && !path.isEmpty()))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Does not contain a valid host:port authority: " + target + helpText
|
||||
);
|
||||
}
|
||||
return new InetSocketAddress(hostname, port);
|
||||
return createSocketAddrForHost(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket address with the given host and port. The hostname
|
||||
* might be replaced with another host that was set via
|
||||
* {@link #addStaticResolution(String, String)}. The value of
|
||||
* hadoop.security.token.service.use_ip will determine whether the
|
||||
* standard java host resolver is used, or if the fully qualified resolver
|
||||
* is used.
|
||||
* @param host the hostname or IP use to instantiate the object
|
||||
* @param port the port number
|
||||
* @return InetSocketAddress
|
||||
*/
|
||||
public static InetSocketAddress createSocketAddrForHost(String host, int port) {
|
||||
String staticHost = getStaticResolution(host);
|
||||
String resolveHost = (staticHost != null) ? staticHost : host;
|
||||
|
||||
InetSocketAddress addr;
|
||||
try {
|
||||
InetAddress iaddr = hostResolver.getByName(resolveHost);
|
||||
// if there is a static entry for the host, make the returned
|
||||
// address look like the original given host
|
||||
if (staticHost != null) {
|
||||
iaddr = InetAddress.getByAddress(host, iaddr.getAddress());
|
||||
}
|
||||
addr = new InetSocketAddress(iaddr, port);
|
||||
} catch (UnknownHostException e) {
|
||||
addr = InetSocketAddress.createUnresolved(host, port);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
interface HostResolver {
|
||||
InetAddress getByName(String host) throws UnknownHostException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses standard java host resolution
|
||||
*/
|
||||
static class StandardHostResolver implements HostResolver {
|
||||
public InetAddress getByName(String host) throws UnknownHostException {
|
||||
return InetAddress.getByName(host);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This an alternate resolver with important properties that the standard
|
||||
* java resolver lacks:
|
||||
* 1) The hostname is fully qualified. This avoids security issues if not
|
||||
* all hosts in the cluster do not share the same search domains. It
|
||||
* also prevents other hosts from performing unnecessary dns searches.
|
||||
* In contrast, InetAddress simply returns the host as given.
|
||||
* 2) The InetAddress is instantiated with an exact host and IP to prevent
|
||||
* further unnecessary lookups. InetAddress may perform an unnecessary
|
||||
* reverse lookup for an IP.
|
||||
* 3) A call to getHostName() will always return the qualified hostname, or
|
||||
* more importantly, the IP if instantiated with an IP. This avoids
|
||||
* unnecessary dns timeouts if the host is not resolvable.
|
||||
* 4) Point 3 also ensures that if the host is re-resolved, ex. during a
|
||||
* connection re-attempt, that a reverse lookup to host and forward
|
||||
* lookup to IP is not performed since the reverse/forward mappings may
|
||||
* not always return the same IP. If the client initiated a connection
|
||||
* with an IP, then that IP is all that should ever be contacted.
|
||||
*
|
||||
* NOTE: this resolver is only used if:
|
||||
* hadoop.security.token.service.use_ip=false
|
||||
*/
|
||||
protected static class QualifiedHostResolver implements HostResolver {
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<String> searchDomains =
|
||||
ResolverConfiguration.open().searchlist();
|
||||
|
||||
/**
|
||||
* Create an InetAddress with a fully qualified hostname of the given
|
||||
* hostname. InetAddress does not qualify an incomplete hostname that
|
||||
* is resolved via the domain search list.
|
||||
* {@link InetAddress#getCanonicalHostName()} will fully qualify the
|
||||
* hostname, but it always return the A record whereas the given hostname
|
||||
* may be a CNAME.
|
||||
*
|
||||
* @param host a hostname or ip address
|
||||
* @return InetAddress with the fully qualified hostname or ip
|
||||
* @throws UnknownHostException if host does not exist
|
||||
*/
|
||||
public InetAddress getByName(String host) throws UnknownHostException {
|
||||
InetAddress addr = null;
|
||||
|
||||
if (IPAddressUtil.isIPv4LiteralAddress(host)) {
|
||||
// use ipv4 address as-is
|
||||
byte[] ip = IPAddressUtil.textToNumericFormatV4(host);
|
||||
addr = InetAddress.getByAddress(host, ip);
|
||||
} else if (IPAddressUtil.isIPv6LiteralAddress(host)) {
|
||||
// use ipv6 address as-is
|
||||
byte[] ip = IPAddressUtil.textToNumericFormatV6(host);
|
||||
addr = InetAddress.getByAddress(host, ip);
|
||||
} else if (host.endsWith(".")) {
|
||||
// a rooted host ends with a dot, ex. "host."
|
||||
// rooted hosts never use the search path, so only try an exact lookup
|
||||
addr = getByExactName(host);
|
||||
} else if (host.contains(".")) {
|
||||
// the host contains a dot (domain), ex. "host.domain"
|
||||
// try an exact host lookup, then fallback to search list
|
||||
addr = getByExactName(host);
|
||||
if (addr == null) {
|
||||
addr = getByNameWithSearch(host);
|
||||
}
|
||||
} else {
|
||||
// it's a simple host with no dots, ex. "host"
|
||||
// try the search list, then fallback to exact host
|
||||
InetAddress loopback = InetAddress.getByName(null);
|
||||
if (host.equalsIgnoreCase(loopback.getHostName())) {
|
||||
addr = InetAddress.getByAddress(host, loopback.getAddress());
|
||||
} else {
|
||||
addr = getByNameWithSearch(host);
|
||||
if (addr == null) {
|
||||
addr = getByExactName(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
// unresolvable!
|
||||
if (addr == null) {
|
||||
throw new UnknownHostException(host);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
InetAddress getByExactName(String host) {
|
||||
InetAddress addr = null;
|
||||
// InetAddress will use the search list unless the host is rooted
|
||||
// with a trailing dot. The trailing dot will disable any use of the
|
||||
// search path in a lower level resolver. See RFC 1535.
|
||||
String fqHost = host;
|
||||
if (!fqHost.endsWith(".")) fqHost += ".";
|
||||
try {
|
||||
addr = getInetAddressByName(fqHost);
|
||||
// can't leave the hostname as rooted or other parts of the system
|
||||
// malfunction, ex. kerberos principals are lacking proper host
|
||||
// equivalence for rooted/non-rooted hostnames
|
||||
addr = InetAddress.getByAddress(host, addr.getAddress());
|
||||
} catch (UnknownHostException e) {
|
||||
// ignore, caller will throw if necessary
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
InetAddress getByNameWithSearch(String host) {
|
||||
InetAddress addr = null;
|
||||
if (host.endsWith(".")) { // already qualified?
|
||||
addr = getByExactName(host);
|
||||
} else {
|
||||
for (String domain : searchDomains) {
|
||||
String dot = !domain.startsWith(".") ? "." : "";
|
||||
addr = getByExactName(host + dot + domain);
|
||||
if (addr != null) break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
// implemented as a separate method to facilitate unit testing
|
||||
InetAddress getInetAddressByName(String host) throws UnknownHostException {
|
||||
return InetAddress.getByName(host);
|
||||
}
|
||||
|
||||
void setSearchDomains(String ... domains) {
|
||||
searchDomains = Arrays.asList(domains);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for testing only!
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static void setHostResolver(HostResolver newResolver) {
|
||||
hostResolver = newResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the uri's hostname and add the default port if not in the uri
|
||||
* @param uri to resolve
|
||||
* @param defaultPort if none is given
|
||||
* @return URI
|
||||
*/
|
||||
public static URI getCanonicalUri(URI uri, int defaultPort) {
|
||||
// skip if there is no authority, ie. "file" scheme or relative uri
|
||||
String host = uri.getHost();
|
||||
if (host == null) {
|
||||
return uri;
|
||||
}
|
||||
String fqHost = canonicalizeHost(host);
|
||||
int port = uri.getPort();
|
||||
// short out if already canonical with a port
|
||||
if (host.equals(fqHost) && port != -1) {
|
||||
return uri;
|
||||
}
|
||||
// reconstruct the uri with the canonical host and port
|
||||
try {
|
||||
uri = new URI(uri.getScheme(), uri.getUserInfo(),
|
||||
fqHost, (port == -1) ? defaultPort : port,
|
||||
uri.getPath(), uri.getQuery(), uri.getFragment());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
// cache the canonicalized hostnames; the cache currently isn't expired,
|
||||
// but the canonicals will only change if the host's resolver configuration
|
||||
// changes
|
||||
private static final ConcurrentHashMap<String, String> canonicalizedHostCache =
|
||||
new ConcurrentHashMap<String, String>();
|
||||
|
||||
private static String canonicalizeHost(String host) {
|
||||
// check if the host has already been canonicalized
|
||||
String fqHost = canonicalizedHostCache.get(host);
|
||||
if (fqHost == null) {
|
||||
try {
|
||||
fqHost = hostResolver.getByName(host).getHostName();
|
||||
// slight race condition, but won't hurt
|
||||
canonicalizedHostCache.put(host, fqHost);
|
||||
} catch (UnknownHostException e) {
|
||||
fqHost = host;
|
||||
}
|
||||
}
|
||||
return fqHost;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,8 +519,8 @@ public static List <String[]> getAllStaticResolutions() {
|
||||
*/
|
||||
public static InetSocketAddress getConnectAddress(Server server) {
|
||||
InetSocketAddress addr = server.getListenerAddress();
|
||||
if (addr.getAddress().getHostAddress().equals("0.0.0.0")) {
|
||||
addr = new InetSocketAddress("127.0.0.1", addr.getPort());
|
||||
if (addr.getAddress().isAnyLocalAddress()) {
|
||||
addr = createSocketAddrForHost("127.0.0.1", addr.getPort());
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
||||
import org.apache.hadoop.io.Text;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.token.Token;
|
||||
@ -50,6 +51,35 @@ public class SecurityUtil {
|
||||
public static final Log LOG = LogFactory.getLog(SecurityUtil.class);
|
||||
public static final String HOSTNAME_PATTERN = "_HOST";
|
||||
|
||||
// controls whether buildTokenService will use an ip or host/ip as given
|
||||
// by the user
|
||||
private static boolean useIpForTokenService;
|
||||
|
||||
static {
|
||||
boolean useIp = new Configuration().getBoolean(
|
||||
CommonConfigurationKeys.HADOOP_SECURITY_TOKEN_SERVICE_USE_IP,
|
||||
CommonConfigurationKeys.HADOOP_SECURITY_TOKEN_SERVICE_USE_IP_DEFAULT);
|
||||
setTokenServiceUseIp(useIp);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use only by tests and initialization
|
||||
*/
|
||||
@InterfaceAudience.Private
|
||||
static void setTokenServiceUseIp(boolean flag) {
|
||||
useIpForTokenService = flag;
|
||||
NetUtils.setUseQualifiedHostResolver(!flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended only for temporary use by NetUtils. Do not use.
|
||||
* @return whether tokens use an IP address
|
||||
*/
|
||||
@InterfaceAudience.Private
|
||||
public static boolean getTokenServiceUseIp() {
|
||||
return useIpForTokenService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the original TGT within the current subject's credentials. Cross-realm
|
||||
* TGT's of the form "krbtgt/TWO.COM@ONE.COM" may be present.
|
||||
@ -263,28 +293,19 @@ public static void login(final Configuration conf,
|
||||
}
|
||||
|
||||
/**
|
||||
* create service name for Delegation token ip:port
|
||||
* @param uri
|
||||
* @param defPort
|
||||
* @return "ip:port"
|
||||
* create the service name for a Delegation token
|
||||
* @param uri of the service
|
||||
* @param defPort is used if the uri lacks a port
|
||||
* @return the token service, or null if no authority
|
||||
* @see #buildTokenService(InetSocketAddress)
|
||||
*/
|
||||
public static String buildDTServiceName(URI uri, int defPort) {
|
||||
int port = uri.getPort();
|
||||
if(port == -1)
|
||||
port = defPort;
|
||||
|
||||
// build the service name string "/ip:port"
|
||||
// for whatever reason using NetUtils.createSocketAddr(target).toString()
|
||||
// returns "localhost/ip:port"
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String host = uri.getHost();
|
||||
if (host != null) {
|
||||
host = NetUtils.normalizeHostName(host);
|
||||
} else {
|
||||
host = "";
|
||||
String authority = uri.getAuthority();
|
||||
if (authority == null) {
|
||||
return null;
|
||||
}
|
||||
sb.append(host).append(":").append(port);
|
||||
return sb.toString();
|
||||
InetSocketAddress addr = NetUtils.createSocketAddr(authority, defPort);
|
||||
return buildTokenService(addr).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -367,22 +388,58 @@ public static TokenInfo getTokenInfo(Class<?> protocol, Configuration conf) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the given token's service field into an InetAddress
|
||||
* @param token from which to obtain the service
|
||||
* @return InetAddress for the service
|
||||
*/
|
||||
public static InetSocketAddress getTokenServiceAddr(Token<?> token) {
|
||||
return NetUtils.createSocketAddr(token.getService().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given token's service to the format expected by the RPC client
|
||||
* @param token a delegation token
|
||||
* @param addr the socket for the rpc connection
|
||||
*/
|
||||
public static void setTokenService(Token<?> token, InetSocketAddress addr) {
|
||||
token.setService(buildTokenService(addr));
|
||||
Text service = buildTokenService(addr);
|
||||
if (token != null) {
|
||||
token.setService(service);
|
||||
LOG.info("Acquired token "+token); // Token#toString() prints service
|
||||
} else {
|
||||
LOG.warn("Failed to get token for service "+service);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the service key for a token
|
||||
* @param addr InetSocketAddress of remote connection with a token
|
||||
* @return "ip:port"
|
||||
* @return "ip:port" or "host:port" depending on the value of
|
||||
* hadoop.security.token.service.use_ip
|
||||
*/
|
||||
public static Text buildTokenService(InetSocketAddress addr) {
|
||||
String host = addr.getAddress().getHostAddress();
|
||||
String host = null;
|
||||
if (useIpForTokenService) {
|
||||
if (addr.isUnresolved()) { // host has no ip address
|
||||
throw new IllegalArgumentException(
|
||||
new UnknownHostException(addr.getHostName())
|
||||
);
|
||||
}
|
||||
host = addr.getAddress().getHostAddress();
|
||||
} else {
|
||||
host = addr.getHostName().toLowerCase();
|
||||
}
|
||||
return new Text(host + ":" + addr.getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the service key for a token
|
||||
* @param uri of remote connection with a token
|
||||
* @return "ip:port" or "host:port" depending on the value of
|
||||
* hadoop.security.token.service.use_ip
|
||||
*/
|
||||
public static Text buildTokenService(URI uri) {
|
||||
return buildTokenService(NetUtils.createSocketAddr(uri.getAuthority()));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,365 @@
|
||||
/**
|
||||
* 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.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.permission.FsPermission;
|
||||
import org.apache.hadoop.net.NetUtilsTestResolver;
|
||||
import org.apache.hadoop.util.Progressable;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestFileSystemCanonicalization extends TestCase {
|
||||
static String[] authorities = {
|
||||
"myfs://host",
|
||||
"myfs://host.a",
|
||||
"myfs://host.a.b",
|
||||
};
|
||||
|
||||
static String[] ips = {
|
||||
"myfs://127.0.0.1"
|
||||
};
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetupResolver() throws Exception {
|
||||
NetUtilsTestResolver.install();
|
||||
}
|
||||
|
||||
// no ports
|
||||
|
||||
@Test
|
||||
public void testShortAuthority() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartialAuthority() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullAuthority() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a.b", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
// with default ports
|
||||
|
||||
@Test
|
||||
public void testShortAuthorityWithDefaultPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host:123", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartialAuthorityWithDefaultPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a:123", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullAuthorityWithDefaultPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a.b:123", "myfs://host.a.b:123");
|
||||
verifyPaths(fs, authorities, -1, true);
|
||||
verifyPaths(fs, authorities, 123, true);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
// with non-standard ports
|
||||
|
||||
@Test
|
||||
public void testShortAuthorityWithOtherPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host:456", "myfs://host.a.b:456");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, true);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartialAuthorityWithOtherPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a:456", "myfs://host.a.b:456");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, true);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullAuthorityWithOtherPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://host.a.b:456", "myfs://host.a.b:456");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, true);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
// ips
|
||||
|
||||
@Test
|
||||
public void testIpAuthority() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://127.0.0.1", "myfs://127.0.0.1:123");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, true);
|
||||
verifyPaths(fs, ips, 123, true);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIpAuthorityWithDefaultPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://127.0.0.1:123", "myfs://127.0.0.1:123");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, true);
|
||||
verifyPaths(fs, ips, 123, true);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIpAuthorityWithOtherPort() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://127.0.0.1:456", "myfs://127.0.0.1:456");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, true);
|
||||
}
|
||||
|
||||
// bad stuff
|
||||
|
||||
@Test
|
||||
public void testMismatchedSchemes() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs2://simple", "myfs2://simple:123");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMismatchedHosts() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs://simple", "myfs://simple:123");
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullAuthority() throws Exception {
|
||||
FileSystem fs = getVerifiedFS("myfs:///", "myfs:///");
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, true);
|
||||
verifyPaths(fs, authorities, -1, false);
|
||||
verifyPaths(fs, authorities, 123, false);
|
||||
verifyPaths(fs, authorities, 456, false);
|
||||
verifyPaths(fs, ips, -1, false);
|
||||
verifyPaths(fs, ips, 123, false);
|
||||
verifyPaths(fs, ips, 456, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthorityFromDefaultFS() throws Exception {
|
||||
Configuration config = new Configuration();
|
||||
String defaultFsKey = CommonConfigurationKeys.FS_DEFAULT_NAME_KEY;
|
||||
|
||||
FileSystem fs = getVerifiedFS("myfs://host", "myfs://host.a.b:123", config);
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, false);
|
||||
|
||||
config.set(defaultFsKey, "myfs://host");
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, true);
|
||||
|
||||
config.set(defaultFsKey, "myfs2://host");
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, false);
|
||||
|
||||
config.set(defaultFsKey, "myfs://host:123");
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, true);
|
||||
|
||||
config.set(defaultFsKey, "myfs://host:456");
|
||||
verifyPaths(fs, new String[]{ "myfs://" }, -1, false);
|
||||
}
|
||||
|
||||
FileSystem getVerifiedFS(String authority, String canonical) throws Exception {
|
||||
return getVerifiedFS(authority, canonical, new Configuration());
|
||||
}
|
||||
|
||||
// create a fs from the authority, then check its uri against the given uri
|
||||
// and the canonical. then try to fetch paths using the canonical
|
||||
FileSystem getVerifiedFS(String authority, String canonical, Configuration conf)
|
||||
throws Exception {
|
||||
URI uri = URI.create(authority);
|
||||
URI canonicalUri = URI.create(canonical);
|
||||
|
||||
FileSystem fs = new DummyFileSystem(uri, conf);
|
||||
assertEquals(uri, fs.getUri());
|
||||
assertEquals(canonicalUri, fs.getCanonicalUri());
|
||||
verifyCheckPath(fs, "/file", true);
|
||||
return fs;
|
||||
}
|
||||
|
||||
void verifyPaths(FileSystem fs, String[] uris, int port, boolean shouldPass) {
|
||||
for (String uri : uris) {
|
||||
if (port != -1) uri += ":"+port;
|
||||
verifyCheckPath(fs, uri+"/file", shouldPass);
|
||||
}
|
||||
}
|
||||
|
||||
void verifyCheckPath(FileSystem fs, String path, boolean shouldPass) {
|
||||
Path rawPath = new Path(path);
|
||||
Path fqPath = null;
|
||||
Exception e = null;
|
||||
try {
|
||||
fqPath = fs.makeQualified(rawPath);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
e = iae;
|
||||
}
|
||||
if (shouldPass) {
|
||||
assertEquals(null, e);
|
||||
String pathAuthority = rawPath.toUri().getAuthority();
|
||||
if (pathAuthority == null) {
|
||||
pathAuthority = fs.getUri().getAuthority();
|
||||
}
|
||||
assertEquals(pathAuthority, fqPath.toUri().getAuthority());
|
||||
} else {
|
||||
assertNotNull("did not fail", e);
|
||||
assertEquals("Wrong FS: "+rawPath+", expected: "+fs.getUri(),
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyFileSystem extends FileSystem {
|
||||
URI uri;
|
||||
static int defaultPort = 123;
|
||||
|
||||
DummyFileSystem(URI uri, Configuration conf) throws IOException {
|
||||
this.uri = uri;
|
||||
setConf(conf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultPort() {
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSDataInputStream open(Path f, int bufferSize) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSDataOutputStream create(Path f, FsPermission permission,
|
||||
boolean overwrite, int bufferSize, short replication, long blockSize,
|
||||
Progressable progress) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSDataOutputStream append(Path f, int bufferSize,
|
||||
Progressable progress) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rename(Path src, Path dst) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Path f, boolean recursive) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStatus[] listStatus(Path f) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorkingDirectory(Path new_dir) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getWorkingDirectory() {
|
||||
return new Path("/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdirs(Path f, FsPermission permission) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStatus getFileStatus(Path f) throws IOException {
|
||||
throw new IOException("not supposed to be here");
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
import org.apache.hadoop.io.Text;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.KerberosInfo;
|
||||
import org.apache.hadoop.security.SecurityUtil;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
import org.apache.hadoop.security.authorize.ProxyUsers;
|
||||
import org.apache.hadoop.security.token.Token;
|
||||
@ -213,8 +214,7 @@ public MiniProtocol run() throws IOException {
|
||||
token = p.getDelegationToken(new Text(RENEWER));
|
||||
currentUgi = UserGroupInformation.createUserForTesting(MINI_USER,
|
||||
GROUP_NAMES);
|
||||
token.setService(new Text(addr.getAddress().getHostAddress()
|
||||
+ ":" + addr.getPort()));
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
currentUgi.addToken(token);
|
||||
return p;
|
||||
}
|
||||
|
@ -287,10 +287,7 @@ private void doDigestRpc(Server server, TestTokenSecretManager sm
|
||||
.getUserName()));
|
||||
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
|
||||
sm);
|
||||
Text host = new Text(addr.getAddress().getHostAddress() + ":"
|
||||
+ addr.getPort());
|
||||
token.setService(host);
|
||||
LOG.info("Service IP address for token is " + host);
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
current.addToken(token);
|
||||
|
||||
TestSaslProtocol proxy = null;
|
||||
@ -362,10 +359,7 @@ public void testPerConnectionConf() throws Exception {
|
||||
.getUserName()));
|
||||
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
|
||||
sm);
|
||||
Text host = new Text(addr.getAddress().getHostAddress() + ":"
|
||||
+ addr.getPort());
|
||||
token.setService(host);
|
||||
LOG.info("Service IP address for token is " + host);
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
current.addToken(token);
|
||||
|
||||
Configuration newConf = new Configuration(conf);
|
||||
@ -452,10 +446,7 @@ public void testDigestAuthMethod() throws Exception {
|
||||
.getUserName()));
|
||||
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
|
||||
sm);
|
||||
Text host = new Text(addr.getAddress().getHostAddress() + ":"
|
||||
+ addr.getPort());
|
||||
token.setService(host);
|
||||
LOG.info("Service IP address for token is " + host);
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
current.addToken(token);
|
||||
|
||||
current.doAs(new PrivilegedExceptionAction<Object>() {
|
||||
|
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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.net;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hadoop.net.NetUtils.QualifiedHostResolver;
|
||||
|
||||
/**
|
||||
* provides a dummy dns search resolver with a configurable search path
|
||||
* and host mapping
|
||||
*/
|
||||
public class NetUtilsTestResolver extends QualifiedHostResolver {
|
||||
Map<String, InetAddress> resolvedHosts = new HashMap<String, InetAddress>();
|
||||
List<String> hostSearches = new LinkedList<String>();
|
||||
|
||||
public static NetUtilsTestResolver install() {
|
||||
NetUtilsTestResolver resolver = new NetUtilsTestResolver();
|
||||
resolver.setSearchDomains("a.b", "b", "c");
|
||||
resolver.addResolvedHost("host.a.b.", "1.1.1.1");
|
||||
resolver.addResolvedHost("b-host.b.", "2.2.2.2");
|
||||
resolver.addResolvedHost("simple.", "3.3.3.3");
|
||||
NetUtils.setHostResolver(resolver);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public void addResolvedHost(String host, String ip) {
|
||||
InetAddress addr;
|
||||
try {
|
||||
addr = InetAddress.getByName(ip);
|
||||
addr = InetAddress.getByAddress(host, addr.getAddress());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("not an ip:"+ip);
|
||||
}
|
||||
resolvedHosts.put(host, addr);
|
||||
}
|
||||
|
||||
InetAddress getInetAddressByName(String host) throws UnknownHostException {
|
||||
hostSearches.add(host);
|
||||
if (!resolvedHosts.containsKey(host)) {
|
||||
throw new UnknownHostException(host);
|
||||
}
|
||||
return resolvedHosts.get(host);
|
||||
}
|
||||
|
||||
String[] getHostSearches() {
|
||||
return hostSearches.toArray(new String[0]);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
hostSearches.clear();
|
||||
}
|
||||
}
|
@ -17,25 +17,29 @@
|
||||
*/
|
||||
package org.apache.hadoop.net;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.Socket;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestNetUtils {
|
||||
|
||||
@ -248,4 +252,255 @@ private IOException verifyExceptionClass(IOException e,
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
static NetUtilsTestResolver resolver;
|
||||
static Configuration config;
|
||||
|
||||
@BeforeClass
|
||||
public static void setupResolver() {
|
||||
resolver = NetUtilsTestResolver.install();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void resetResolver() {
|
||||
resolver.reset();
|
||||
config = new Configuration();
|
||||
}
|
||||
|
||||
// getByExactName
|
||||
|
||||
private void verifyGetByExactNameSearch(String host, String ... searches) {
|
||||
assertNull(resolver.getByExactName(host));
|
||||
assertBetterArrayEquals(searches, resolver.getHostSearches());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByExactNameUnqualified() {
|
||||
verifyGetByExactNameSearch("unknown", "unknown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByExactNameUnqualifiedWithDomain() {
|
||||
verifyGetByExactNameSearch("unknown.domain", "unknown.domain.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByExactNameQualified() {
|
||||
verifyGetByExactNameSearch("unknown.", "unknown.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByExactNameQualifiedWithDomain() {
|
||||
verifyGetByExactNameSearch("unknown.domain.", "unknown.domain.");
|
||||
}
|
||||
|
||||
// getByNameWithSearch
|
||||
|
||||
private void verifyGetByNameWithSearch(String host, String ... searches) {
|
||||
assertNull(resolver.getByNameWithSearch(host));
|
||||
assertBetterArrayEquals(searches, resolver.getHostSearches());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameWithSearchUnqualified() {
|
||||
String host = "unknown";
|
||||
verifyGetByNameWithSearch(host, host+".a.b.", host+".b.", host+".c.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameWithSearchUnqualifiedWithDomain() {
|
||||
String host = "unknown.domain";
|
||||
verifyGetByNameWithSearch(host, host+".a.b.", host+".b.", host+".c.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameWithSearchQualified() {
|
||||
String host = "unknown.";
|
||||
verifyGetByNameWithSearch(host, host);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameWithSearchQualifiedWithDomain() {
|
||||
String host = "unknown.domain.";
|
||||
verifyGetByNameWithSearch(host, host);
|
||||
}
|
||||
|
||||
// getByName
|
||||
|
||||
private void verifyGetByName(String host, String ... searches) {
|
||||
InetAddress addr = null;
|
||||
try {
|
||||
addr = resolver.getByName(host);
|
||||
} catch (UnknownHostException e) {} // ignore
|
||||
assertNull(addr);
|
||||
assertBetterArrayEquals(searches, resolver.getHostSearches());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameQualified() {
|
||||
String host = "unknown.";
|
||||
verifyGetByName(host, host);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameQualifiedWithDomain() {
|
||||
verifyGetByName("unknown.domain.", "unknown.domain.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameUnqualified() {
|
||||
String host = "unknown";
|
||||
verifyGetByName(host, host+".a.b.", host+".b.", host+".c.", host+".");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverGetByNameUnqualifiedWithDomain() {
|
||||
String host = "unknown.domain";
|
||||
verifyGetByName(host, host+".", host+".a.b.", host+".b.", host+".c.");
|
||||
}
|
||||
|
||||
// resolving of hosts
|
||||
|
||||
private InetAddress verifyResolve(String host, String ... searches) {
|
||||
InetAddress addr = null;
|
||||
try {
|
||||
addr = resolver.getByName(host);
|
||||
} catch (UnknownHostException e) {} // ignore
|
||||
assertNotNull(addr);
|
||||
assertBetterArrayEquals(searches, resolver.getHostSearches());
|
||||
return addr;
|
||||
}
|
||||
|
||||
private void
|
||||
verifyInetAddress(InetAddress addr, String host, String ip) {
|
||||
assertNotNull(addr);
|
||||
assertEquals(host, addr.getHostName());
|
||||
assertEquals(ip, addr.getHostAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverUnqualified() {
|
||||
String host = "host";
|
||||
InetAddress addr = verifyResolve(host, host+".a.b.");
|
||||
verifyInetAddress(addr, "host.a.b", "1.1.1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverUnqualifiedWithDomain() {
|
||||
String host = "host.a";
|
||||
InetAddress addr = verifyResolve(host, host+".", host+".a.b.", host+".b.");
|
||||
verifyInetAddress(addr, "host.a.b", "1.1.1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverUnqualifedFull() {
|
||||
String host = "host.a.b";
|
||||
InetAddress addr = verifyResolve(host, host+".");
|
||||
verifyInetAddress(addr, host, "1.1.1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverQualifed() {
|
||||
String host = "host.a.b.";
|
||||
InetAddress addr = verifyResolve(host, host);
|
||||
verifyInetAddress(addr, host, "1.1.1.1");
|
||||
}
|
||||
|
||||
// localhost
|
||||
|
||||
@Test
|
||||
public void testResolverLoopback() {
|
||||
String host = "Localhost";
|
||||
InetAddress addr = verifyResolve(host); // no lookup should occur
|
||||
verifyInetAddress(addr, "Localhost", "127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolverIP() {
|
||||
String host = "1.1.1.1";
|
||||
InetAddress addr = verifyResolve(host); // no lookup should occur for ips
|
||||
verifyInetAddress(addr, host, host);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithPort() {
|
||||
URI uri;
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host:123"), 456);
|
||||
assertEquals("scheme://host.a.b:123", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host:123/"), 456);
|
||||
assertEquals("scheme://host.a.b:123/", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host:123/path"), 456);
|
||||
assertEquals("scheme://host.a.b:123/path", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host:123/path?q#frag"), 456);
|
||||
assertEquals("scheme://host.a.b:123/path?q#frag", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithDefaultPort() {
|
||||
URI uri;
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host"), 123);
|
||||
assertEquals("scheme://host.a.b:123", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host/"), 123);
|
||||
assertEquals("scheme://host.a.b:123/", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host/path"), 123);
|
||||
assertEquals("scheme://host.a.b:123/path", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme://host/path?q#frag"), 123);
|
||||
assertEquals("scheme://host.a.b:123/path?q#frag", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithPath() {
|
||||
URI uri;
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("path"), 2);
|
||||
assertEquals("path", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("/path"), 2);
|
||||
assertEquals("/path", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithNoAuthority() {
|
||||
URI uri;
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme:/"), 2);
|
||||
assertEquals("scheme:/", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme:/path"), 2);
|
||||
assertEquals("scheme:/path", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme:///"), 2);
|
||||
assertEquals("scheme:///", uri.toString());
|
||||
|
||||
uri = NetUtils.getCanonicalUri(URI.create("scheme:///path"), 2);
|
||||
assertEquals("scheme:///path", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithNoHost() {
|
||||
URI uri = NetUtils.getCanonicalUri(URI.create("scheme://:123/path"), 2);
|
||||
assertEquals("scheme://:123/path", uri.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalUriWithNoPortNoDefaultPort() {
|
||||
URI uri = NetUtils.getCanonicalUri(URI.create("scheme://host/path"), -1);
|
||||
assertEquals("scheme://host.a.b/path", uri.toString());
|
||||
}
|
||||
|
||||
private <T> void assertBetterArrayEquals(T[] expect, T[]got) {
|
||||
String expectStr = StringUtils.join(expect, ", ");
|
||||
String gotStr = StringUtils.join(got, ", ");
|
||||
assertEquals(expectStr, gotStr);
|
||||
}
|
||||
}
|
@ -418,9 +418,7 @@ public void testProxyWithToken() throws Exception {
|
||||
.getUserName()), new Text("SomeSuperUser"));
|
||||
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
|
||||
sm);
|
||||
Text host = new Text(addr.getAddress().getHostAddress() + ":"
|
||||
+ addr.getPort());
|
||||
token.setService(host);
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
UserGroupInformation proxyUserUgi = UserGroupInformation
|
||||
.createProxyUserForTesting(PROXY_USER_NAME, current, GROUP_NAMES);
|
||||
proxyUserUgi.addToken(token);
|
||||
@ -476,9 +474,7 @@ public void testTokenBySuperUser() throws Exception {
|
||||
.getUserName()), new Text("SomeSuperUser"));
|
||||
Token<TestTokenIdentifier> token = new Token<TestTokenIdentifier>(tokenId,
|
||||
sm);
|
||||
Text host = new Text(addr.getAddress().getHostAddress() + ":"
|
||||
+ addr.getPort());
|
||||
token.setService(host);
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
current.addToken(token);
|
||||
String retVal = current.doAs(new PrivilegedExceptionAction<String>() {
|
||||
@Override
|
||||
|
@ -16,16 +16,19 @@
|
||||
*/
|
||||
package org.apache.hadoop.security;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.io.Text;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.token.Token;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@ -121,4 +124,213 @@ public void testGetHostFromPrincipal() {
|
||||
assertEquals(null,
|
||||
SecurityUtil.getHostFromPrincipal("service@realm"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildDTServiceName() {
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildDTServiceName(URI.create("test://LocalHost"), 123)
|
||||
);
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildDTServiceName(URI.create("test://LocalHost:123"), 456)
|
||||
);
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildDTServiceName(URI.create("test://127.0.0.1"), 123)
|
||||
);
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildDTServiceName(URI.create("test://127.0.0.1:123"), 456)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildTokenServiceSockAddr() {
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildTokenService(new InetSocketAddress("LocalHost", 123)).toString()
|
||||
);
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildTokenService(new InetSocketAddress("127.0.0.1", 123)).toString()
|
||||
);
|
||||
// what goes in, comes out
|
||||
assertEquals("127.0.0.1:123",
|
||||
SecurityUtil.buildTokenService(NetUtils.createSocketAddr("127.0.0.1", 123)).toString()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGoodHostsAndPorts() {
|
||||
InetSocketAddress compare = NetUtils.createSocketAddrForHost("localhost", 123);
|
||||
runGoodCases(compare, "localhost", 123);
|
||||
runGoodCases(compare, "localhost:", 123);
|
||||
runGoodCases(compare, "localhost:123", 456);
|
||||
}
|
||||
|
||||
void runGoodCases(InetSocketAddress addr, String host, int port) {
|
||||
assertEquals(addr, NetUtils.createSocketAddr(host, port));
|
||||
assertEquals(addr, NetUtils.createSocketAddr("hdfs://"+host, port));
|
||||
assertEquals(addr, NetUtils.createSocketAddr("hdfs://"+host+"/path", port));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHostsAndPorts() {
|
||||
runBadCases("", true);
|
||||
runBadCases(":", false);
|
||||
runBadCases("hdfs/", false);
|
||||
runBadCases("hdfs:/", false);
|
||||
runBadCases("hdfs://", true);
|
||||
}
|
||||
|
||||
void runBadCases(String prefix, boolean validIfPosPort) {
|
||||
runBadPortPermutes(prefix, false);
|
||||
runBadPortPermutes(prefix+"*", false);
|
||||
runBadPortPermutes(prefix+"localhost", validIfPosPort);
|
||||
runBadPortPermutes(prefix+"localhost:-1", false);
|
||||
runBadPortPermutes(prefix+"localhost:-123", false);
|
||||
runBadPortPermutes(prefix+"localhost:xyz", false);
|
||||
runBadPortPermutes(prefix+"localhost/xyz", validIfPosPort);
|
||||
runBadPortPermutes(prefix+"localhost/:123", validIfPosPort);
|
||||
runBadPortPermutes(prefix+":123", false);
|
||||
runBadPortPermutes(prefix+":xyz", false);
|
||||
}
|
||||
|
||||
void runBadPortPermutes(String arg, boolean validIfPosPort) {
|
||||
int ports[] = { -123, -1, 123 };
|
||||
boolean bad = false;
|
||||
try {
|
||||
NetUtils.createSocketAddr(arg);
|
||||
} catch (IllegalArgumentException e) {
|
||||
bad = true;
|
||||
} finally {
|
||||
assertTrue("should be bad: '"+arg+"'", bad);
|
||||
}
|
||||
for (int port : ports) {
|
||||
if (validIfPosPort && port > 0) continue;
|
||||
|
||||
bad = false;
|
||||
try {
|
||||
NetUtils.createSocketAddr(arg, port);
|
||||
} catch (IllegalArgumentException e) {
|
||||
bad = true;
|
||||
} finally {
|
||||
assertTrue("should be bad: '"+arg+"' (default port:"+port+")", bad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check that the socket addr has:
|
||||
// 1) the InetSocketAddress has the correct hostname, ie. exact host/ip given
|
||||
// 2) the address is resolved, ie. has an ip
|
||||
// 3,4) the socket's InetAddress has the same hostname, and the correct ip
|
||||
// 5) the port is correct
|
||||
private void
|
||||
verifyValues(InetSocketAddress addr, String host, String ip, int port) {
|
||||
assertTrue(!addr.isUnresolved());
|
||||
// don't know what the standard resolver will return for hostname.
|
||||
// should be host for host; host or ip for ip is ambiguous
|
||||
if (!SecurityUtil.getTokenServiceUseIp()) {
|
||||
assertEquals(host, addr.getHostName());
|
||||
assertEquals(host, addr.getAddress().getHostName());
|
||||
}
|
||||
assertEquals(ip, addr.getAddress().getHostAddress());
|
||||
assertEquals(port, addr.getPort());
|
||||
}
|
||||
|
||||
// check:
|
||||
// 1) buildTokenService honors use_ip setting
|
||||
// 2) setTokenService & getService works
|
||||
// 3) getTokenServiceAddr decodes to the identical socket addr
|
||||
private void
|
||||
verifyTokenService(InetSocketAddress addr, String host, String ip, int port, boolean useIp) {
|
||||
//LOG.info("address:"+addr+" host:"+host+" ip:"+ip+" port:"+port);
|
||||
|
||||
SecurityUtil.setTokenServiceUseIp(useIp);
|
||||
String serviceHost = useIp ? ip : host.toLowerCase();
|
||||
|
||||
Token token = new Token();
|
||||
Text service = new Text(serviceHost+":"+port);
|
||||
|
||||
assertEquals(service, SecurityUtil.buildTokenService(addr));
|
||||
SecurityUtil.setTokenService(token, addr);
|
||||
assertEquals(service, token.getService());
|
||||
|
||||
InetSocketAddress serviceAddr = SecurityUtil.getTokenServiceAddr(token);
|
||||
assertNotNull(serviceAddr);
|
||||
verifyValues(serviceAddr, serviceHost, ip, port);
|
||||
}
|
||||
|
||||
// check:
|
||||
// 1) socket addr is created with fields set as expected
|
||||
// 2) token service with ips
|
||||
// 3) token service with the given host or ip
|
||||
private void
|
||||
verifyAddress(InetSocketAddress addr, String host, String ip, int port) {
|
||||
verifyValues(addr, host, ip, port);
|
||||
//LOG.info("test that token service uses ip");
|
||||
verifyTokenService(addr, host, ip, port, true);
|
||||
//LOG.info("test that token service uses host");
|
||||
verifyTokenService(addr, host, ip, port, false);
|
||||
}
|
||||
|
||||
// check:
|
||||
// 1-4) combinations of host and port
|
||||
// this will construct a socket addr, verify all the fields, build the
|
||||
// service to verify the use_ip setting is honored, set the token service
|
||||
// based on addr and verify the token service is set correctly, decode
|
||||
// the token service and ensure all the fields of the decoded addr match
|
||||
private void verifyServiceAddr(String host, String ip) {
|
||||
InetSocketAddress addr;
|
||||
int port = 123;
|
||||
|
||||
// test host, port tuple
|
||||
//LOG.info("test tuple ("+host+","+port+")");
|
||||
addr = NetUtils.createSocketAddrForHost(host, port);
|
||||
verifyAddress(addr, host, ip, port);
|
||||
|
||||
// test authority with no default port
|
||||
//LOG.info("test authority '"+host+":"+port+"'");
|
||||
addr = NetUtils.createSocketAddr(host+":"+port);
|
||||
verifyAddress(addr, host, ip, port);
|
||||
|
||||
// test authority with a default port, make sure default isn't used
|
||||
//LOG.info("test authority '"+host+":"+port+"' with ignored default port");
|
||||
addr = NetUtils.createSocketAddr(host+":"+port, port+1);
|
||||
verifyAddress(addr, host, ip, port);
|
||||
|
||||
// test host-only authority, using port as default port
|
||||
//LOG.info("test host:"+host+" port:"+port);
|
||||
addr = NetUtils.createSocketAddr(host, port);
|
||||
verifyAddress(addr, host, ip, port);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocketAddrWithName() {
|
||||
String staticHost = "my";
|
||||
NetUtils.addStaticResolution(staticHost, "localhost");
|
||||
verifyServiceAddr("LocalHost", "127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocketAddrWithIP() {
|
||||
verifyServiceAddr("127.0.0.1", "127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocketAddrWithNameToStaticName() {
|
||||
String staticHost = "host1";
|
||||
NetUtils.addStaticResolution(staticHost, "localhost");
|
||||
verifyServiceAddr(staticHost, "127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocketAddrWithNameToStaticIP() {
|
||||
String staticHost = "host3";
|
||||
NetUtils.addStaticResolution(staticHost, "255.255.255.255");
|
||||
verifyServiceAddr(staticHost, "255.255.255.255");
|
||||
}
|
||||
|
||||
// this is a bizarre case, but it's if a test tries to remap an ip address
|
||||
@Test
|
||||
public void testSocketAddrWithIPToStaticIP() {
|
||||
String staticHost = "1.2.3.4";
|
||||
NetUtils.addStaticResolution(staticHost, "255.255.255.255");
|
||||
verifyServiceAddr(staticHost, "255.255.255.255");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user