HDFS-3312. In HftpFileSystem, the namenode URI is non-secure but the delegation tokens have to use secure URI. Contributed by Daryn Sharp
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1329462 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
80ab78c217
commit
93c5585d31
@ -890,6 +890,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
|
||||||
|
@ -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 @@ protected InetSocketAddress getNamenodeSecureAddr(URI uri) {
|
|||||||
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 void initialize(final URI name, final Configuration conf)
|
|||||||
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 @@ protected void initDelegationToken() throws IOException {
|
|||||||
|
|
||||||
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 synchronized Token<?> getDelegationToken(final String renewer
|
|||||||
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 URI getUri() {
|
|||||||
* @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);
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,17 @@ protected InetSocketAddress getNamenodeSecureAddr(URI uri) {
|
|||||||
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());
|
||||||
|
@ -70,32 +70,74 @@ public FileSystem run() throws Exception {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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 int getDefaultPort() {
|
|||||||
@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 {}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user