svn merge -c 1329462 from trunk for HDFS-3312. In HftpFileSystem, the namenode URI is non-secure but the delegation tokens have to use secure URI.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1329464 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tsz-wo Sze 2012-04-23 21:29:18 +00:00
parent 88d736ce2b
commit e360e796ef
4 changed files with 94 additions and 22 deletions

View File

@ -767,6 +767,9 @@ Release 0.23.3 - UNRELEASED
HDFS-3308. Uses canonical URI to select delegation tokens in HftpFileSystem HDFS-3308. Uses canonical URI to select delegation tokens in HftpFileSystem
and WebHdfsFileSystem. (Daryn Sharp via szetszwo) and WebHdfsFileSystem. (Daryn Sharp via szetszwo)
HDFS-3312. In HftpFileSystem, the namenode URI is non-secure but the
delegation tokens have to use secure URI. (Daryn Sharp via szetszwo)
Release 0.23.2 - UNRELEASED Release 0.23.2 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -94,8 +94,8 @@ public class HftpFileSystem extends FileSystem
protected UserGroupInformation ugi; protected UserGroupInformation ugi;
private URI hftpURI; private URI hftpURI;
protected InetSocketAddress nnAddr; protected URI nnUri;
protected InetSocketAddress nnSecureAddr; protected URI nnSecureUri;
public static final String HFTP_TIMEZONE = "UTC"; public static final String HFTP_TIMEZONE = "UTC";
public static final String HFTP_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; public static final String HFTP_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
@ -139,11 +139,19 @@ public class HftpFileSystem extends FileSystem
return NetUtils.createSocketAddrForHost(uri.getHost(), getDefaultSecurePort()); return NetUtils.createSocketAddrForHost(uri.getHost(), getDefaultSecurePort());
} }
protected URI getNamenodeUri(URI uri) {
return DFSUtil.createUri("http", getNamenodeAddr(uri));
}
protected URI getNamenodeSecureUri(URI uri) {
return DFSUtil.createUri("https", getNamenodeSecureAddr(uri));
}
@Override @Override
public String getCanonicalServiceName() { public String getCanonicalServiceName() {
// unlike other filesystems, hftp's service is the secure port, not the // unlike other filesystems, hftp's service is the secure port, not the
// actual port in the uri // actual port in the uri
return SecurityUtil.buildTokenService(nnSecureAddr).toString(); return SecurityUtil.buildTokenService(nnSecureUri).toString();
} }
@Override @Override
@ -152,8 +160,8 @@ public class HftpFileSystem extends FileSystem
super.initialize(name, conf); super.initialize(name, conf);
setConf(conf); setConf(conf);
this.ugi = UserGroupInformation.getCurrentUser(); this.ugi = UserGroupInformation.getCurrentUser();
this.nnAddr = getNamenodeAddr(name); this.nnUri = getNamenodeUri(name);
this.nnSecureAddr = getNamenodeSecureAddr(name); this.nnSecureUri = getNamenodeSecureUri(name);
try { try {
this.hftpURI = new URI(name.getScheme(), name.getAuthority(), this.hftpURI = new URI(name.getScheme(), name.getAuthority(),
null, null, null); null, null, null);
@ -191,7 +199,7 @@ public class HftpFileSystem extends FileSystem
protected Token<DelegationTokenIdentifier> selectDelegationToken( protected Token<DelegationTokenIdentifier> selectDelegationToken(
UserGroupInformation ugi) { UserGroupInformation ugi) {
return hftpTokenSelector.selectToken(getCanonicalUri(), ugi.getTokens(), getConf()); return hftpTokenSelector.selectToken(nnSecureUri, ugi.getTokens(), getConf());
} }
@ -222,7 +230,7 @@ public class HftpFileSystem extends FileSystem
ugi.reloginFromKeytab(); ugi.reloginFromKeytab();
return ugi.doAs(new PrivilegedExceptionAction<Token<?>>() { return ugi.doAs(new PrivilegedExceptionAction<Token<?>>() {
public Token<?> run() throws IOException { public Token<?> run() throws IOException {
final String nnHttpUrl = DFSUtil.createUri("https", nnSecureAddr).toString(); final String nnHttpUrl = nnSecureUri.toString();
Credentials c; Credentials c;
try { try {
c = DelegationTokenFetcher.getDTfromRemote(nnHttpUrl, renewer); c = DelegationTokenFetcher.getDTfromRemote(nnHttpUrl, renewer);
@ -264,8 +272,8 @@ public class HftpFileSystem extends FileSystem
* @throws IOException on error constructing the URL * @throws IOException on error constructing the URL
*/ */
protected URL getNamenodeURL(String path, String query) throws IOException { protected URL getNamenodeURL(String path, String query) throws IOException {
final URL url = new URL("http", nnAddr.getHostName(), final URL url = new URL("http", nnUri.getHost(),
nnAddr.getPort(), path + '?' + query); nnUri.getPort(), path + '?' + query);
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("url=" + url); LOG.trace("url=" + url);
} }

View File

@ -132,12 +132,17 @@ public class HsftpFileSystem extends HftpFileSystem {
return getNamenodeAddr(uri); return getNamenodeAddr(uri);
} }
@Override
protected URI getNamenodeUri(URI uri) {
return getNamenodeSecureUri(uri);
}
@Override @Override
protected HttpURLConnection openConnection(String path, String query) protected HttpURLConnection openConnection(String path, String query)
throws IOException { throws IOException {
query = addDelegationTokenParam(query); query = addDelegationTokenParam(query);
final URL url = new URL("https", nnAddr.getHostName(), final URL url = new URL("https", nnUri.getHost(),
nnAddr.getPort(), path + '?' + query); nnUri.getPort(), path + '?' + query);
HttpsURLConnection conn = (HttpsURLConnection)URLUtils.openConnection(url); HttpsURLConnection conn = (HttpsURLConnection)URLUtils.openConnection(url);
// bypass hostname verification // bypass hostname verification
conn.setHostnameVerifier(new DummyHostnameVerifier()); conn.setHostnameVerifier(new DummyHostnameVerifier());

View File

@ -70,32 +70,74 @@ public class TestHftpDelegationToken {
} }
@Test @Test
public void testSelectHdfsDelegationToken() throws Exception { public void testSelectHftpDelegationToken() throws Exception {
SecurityUtilTestHelper.setTokenServiceUseIp(true); SecurityUtilTestHelper.setTokenServiceUseIp(true);
Configuration conf = new Configuration(); Configuration conf = new Configuration();
conf.setClass("fs.hftp.impl", MyHftpFileSystem.class, FileSystem.class); conf.setClass("fs.hftp.impl", MyHftpFileSystem.class, FileSystem.class);
int httpPort = 80;
int httpsPort = 443;
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTP_PORT_KEY, httpPort);
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTPS_PORT_KEY, httpsPort);
// test with implicit default port // test with implicit default port
URI fsUri = URI.create("hftp://localhost"); URI fsUri = URI.create("hftp://localhost");
MyHftpFileSystem fs = (MyHftpFileSystem) FileSystem.get(fsUri, conf); MyHftpFileSystem fs = (MyHftpFileSystem) FileSystem.newInstance(fsUri, conf);
checkTokenSelection(fs, conf); assertEquals(httpPort, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort, conf); // should still use secure port
// test with explicit default port // test with explicit default port
fsUri = URI.create("hftp://localhost:"+fs.getDefaultPort()); fsUri = URI.create("hftp://localhost:"+httpPort);
fs = (MyHftpFileSystem) FileSystem.get(fsUri, conf); fs = (MyHftpFileSystem) FileSystem.newInstance(fsUri, conf);
checkTokenSelection(fs, conf); assertEquals(httpPort, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort, conf); // should still use secure port
// test with non-default port // test with non-default port
fsUri = URI.create("hftp://localhost:"+(fs.getDefaultPort()-1)); fsUri = URI.create("hftp://localhost:"+(httpPort+1));
fs = (MyHftpFileSystem) FileSystem.get(fsUri, conf); fs = (MyHftpFileSystem) FileSystem.newInstance(fsUri, conf);
checkTokenSelection(fs, conf); assertEquals(httpPort+1, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort, conf); // should still use secure port
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTPS_PORT_KEY, 5);
} }
private void checkTokenSelection(MyHftpFileSystem fs, @Test
public void testSelectHsftpDelegationToken() throws Exception {
SecurityUtilTestHelper.setTokenServiceUseIp(true);
Configuration conf = new Configuration();
conf.setClass("fs.hsftp.impl", MyHsftpFileSystem.class, FileSystem.class);
int httpPort = 80;
int httpsPort = 443;
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTP_PORT_KEY, httpPort);
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTPS_PORT_KEY, httpsPort);
// test with implicit default port
URI fsUri = URI.create("hsftp://localhost");
MyHsftpFileSystem fs = (MyHsftpFileSystem) FileSystem.newInstance(fsUri, conf);
assertEquals(httpsPort, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort, conf);
// test with explicit default port
fsUri = URI.create("hsftp://localhost:"+httpsPort);
fs = (MyHsftpFileSystem) FileSystem.newInstance(fsUri, conf);
assertEquals(httpsPort, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort, conf);
// test with non-default port
fsUri = URI.create("hsftp://localhost:"+(httpsPort+1));
fs = (MyHsftpFileSystem) FileSystem.newInstance(fsUri, conf);
assertEquals(httpsPort+1, fs.getCanonicalUri().getPort());
checkTokenSelection(fs, httpsPort+1, conf);
conf.setInt(DFSConfigKeys.DFS_NAMENODE_HTTPS_PORT_KEY, 5);
}
private void checkTokenSelection(HftpFileSystem fs,
int port,
Configuration conf) throws IOException { Configuration conf) throws IOException {
int port = fs.getCanonicalUri().getPort();
UserGroupInformation ugi = UserGroupInformation ugi =
UserGroupInformation.createUserForTesting(fs.getUri().getAuthority(), new String[]{}); UserGroupInformation.createUserForTesting(fs.getUri().getAuthority(), new String[]{});
@ -161,4 +203,18 @@ public class TestHftpDelegationToken {
@Override @Override
protected void initDelegationToken() throws IOException {} protected void initDelegationToken() throws IOException {}
} }
static class MyHsftpFileSystem extends HsftpFileSystem {
@Override
public URI getCanonicalUri() {
return super.getCanonicalUri();
}
@Override
public int getDefaultPort() {
return super.getDefaultPort();
}
// don't automatically get a token
@Override
protected void initDelegationToken() throws IOException {}
}
} }