HDFS-15465. Support WebHDFS accesses to the data stored in secure Datanode through insecure Namenode. (#2135)
This commit is contained in:
parent
60a254621a
commit
026dce5334
|
@ -72,9 +72,12 @@ public class DataNodeUGIProvider {
|
|||
UserGroupInformation ugi;
|
||||
|
||||
try {
|
||||
if (UserGroupInformation.isSecurityEnabled()) {
|
||||
final Token<DelegationTokenIdentifier> token = params.delegationToken();
|
||||
|
||||
// Create nonTokenUGI when token is null regardless of security.
|
||||
// This makes it possible to access the data stored in secure DataNode
|
||||
// through insecure Namenode.
|
||||
if (UserGroupInformation.isSecurityEnabled() && token != null) {
|
||||
ugi = ugiCache.get(buildTokenCacheKey(token),
|
||||
new Callable<UserGroupInformation>() {
|
||||
@Override
|
||||
|
@ -134,7 +137,8 @@ public class DataNodeUGIProvider {
|
|||
return key;
|
||||
}
|
||||
|
||||
private UserGroupInformation nonTokenUGI(String usernameFromQuery,
|
||||
@VisibleForTesting
|
||||
UserGroupInformation nonTokenUGI(String usernameFromQuery,
|
||||
String doAsUserFromQuery, String remoteUser) throws IOException {
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation
|
||||
|
|
|
@ -123,6 +123,9 @@ class ParameterParser {
|
|||
|
||||
Token<DelegationTokenIdentifier> delegationToken() throws IOException {
|
||||
String delegation = param(DelegationParam.NAME);
|
||||
if (delegation == null) {
|
||||
return null;
|
||||
}
|
||||
final Token<DelegationTokenIdentifier> token = new
|
||||
Token<DelegationTokenIdentifier>();
|
||||
token.decodeFromUrlString(delegation);
|
||||
|
|
|
@ -335,8 +335,8 @@ public class WebHdfsHandler extends SimpleChannelInboundHandler<HttpRequest> {
|
|||
}
|
||||
|
||||
private void injectToken() throws IOException {
|
||||
if (UserGroupInformation.isSecurityEnabled()) {
|
||||
Token<DelegationTokenIdentifier> token = params.delegationToken();
|
||||
if (UserGroupInformation.isSecurityEnabled() && token != null) {
|
||||
token.setKind(HDFS_DELEGATION_KIND);
|
||||
ugi.addToken(token);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.hadoop.hdfs.server.datanode.web.webhdfs;
|
|||
|
||||
import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -31,6 +33,7 @@ import org.apache.hadoop.fs.FileSystem;
|
|||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||
import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
|
||||
import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenSecretManager;
|
||||
import org.apache.hadoop.hdfs.server.common.JspHelper;
|
||||
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
|
||||
import org.apache.hadoop.hdfs.web.WebHdfsConstants;
|
||||
import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
|
||||
|
@ -186,6 +189,35 @@ public class TestDataNodeUGIProvider {
|
|||
ugi11, url22);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUGINullTokenSecure() throws IOException {
|
||||
SecurityUtil.setAuthenticationMethod(KERBEROS, conf);
|
||||
UserGroupInformation.setConfiguration(conf);
|
||||
|
||||
String uri1 = WebHdfsFileSystem.PATH_PREFIX
|
||||
+ PATH
|
||||
+ "?op=OPEN"
|
||||
+ Param.toSortedString("&", new OffsetParam((long) OFFSET),
|
||||
new LengthParam((long) LENGTH), new UserParam("root"));
|
||||
|
||||
ParameterParser params = new ParameterParser(
|
||||
new QueryStringDecoder(URI.create(uri1)), conf);
|
||||
|
||||
DataNodeUGIProvider ugiProvider = new DataNodeUGIProvider(params);
|
||||
|
||||
String usernameFromQuery = params.userName();
|
||||
String doAsUserFromQuery = params.doAsUser();
|
||||
String remoteUser = usernameFromQuery == null ? JspHelper
|
||||
.getDefaultWebUserName(params.conf())
|
||||
: usernameFromQuery;
|
||||
|
||||
DataNodeUGIProvider spiedUGIProvider = spy(ugiProvider);
|
||||
spiedUGIProvider.ugi();
|
||||
|
||||
verify(spiedUGIProvider).nonTokenUGI(usernameFromQuery, doAsUserFromQuery,
|
||||
remoteUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for expiration of entries from the UGI cache. We need to be careful
|
||||
* not to touch the entries in the cache while we're waiting for expiration.
|
||||
|
|
|
@ -55,6 +55,15 @@ public class TestParameterParser {
|
|||
Assert.assertTrue(HAUtilClient.isTokenForLogicalUri(tok2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullToken() throws IOException {
|
||||
Configuration conf = new Configuration();
|
||||
QueryStringDecoder decoder = new QueryStringDecoder(
|
||||
WebHdfsHandler.WEBHDFS_PREFIX + "/test");
|
||||
ParameterParser testParser = new ParameterParser(decoder, conf);
|
||||
Assert.assertNull(testParser.delegationToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodePath() {
|
||||
final String ESCAPED_PATH = "/test%25+1%26%3Dtest?op=OPEN&foo=bar";
|
||||
|
|
Loading…
Reference in New Issue