我正试图代表另一个用户访问hdfs。我正在尝试以下应用程序
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.log4j.Logger;
import org.apache.hadoop.fs.FSDataOutputStream;
import java.security.PrivilegedExceptionAction;
public class HDFSProxyTest {
public static void main (String[] args) throws Exception {
String hadoopConfigurationPath = "/etc/hadoop/conf/";
final Configuration hdfsConfiguration = new Configuration();
FileSystem localFileSystem = FileSystem.getLocal(hdfsConfiguration);
Path coreSitePath = new Path(hadoopConfigurationPath+"core-site.xml");
hdfsConfiguration.addResource(coreSitePath);
Path hdfsSitePath = new Path(hadoopConfigurationPath+"hdfs-site.xml");
hdfsConfiguration.addResource(hdfsSitePath);
UserGroupInformation.setConfiguration(hdfsConfiguration);
UserGroupInformation.loginUserFromKeytab("striim1@FCE.CLOUDERA.COM", "/home/striim/striim1_client.keytab");
UserGroupInformation ugi =
UserGroupInformation.createProxyUser("joy", UserGroupInformation.getLoginUser());
FileSystem hadoopFileSystem =ugi.doAs(new PrivilegedExceptionAction<FileSystem>() {
public FileSystem run() throws Exception {
return FileSystem.get(hdfsConfiguration);
}
});
FSDataOutputStream fsDataOutputStream = hadoopFileSystem.create(new Path("/user/striim1/hdfsproxy.csv"));
fsDataOutputStream.write("This is niranjan!!! testing this\n".getBytes());
fsDataOutputStream.close();
hadoopFileSystem.close();
}
}
这里这个应用程序执行用户是striim,我尝试模拟的超级用户是striim1,他拥有kerberos凭据,joy是我尝试代表他访问hdfs的用户。
我最终得到了这个例外。
2017-05-19 02:45:34,843 - WARN main org.apache.hadoop.util.NativeCodeLoader.<clinit> (NativeCodeLoader.java:62) Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: user=joy, access=WRITE, inode="/user/striim1":striim1:striim1:drwxr-xr-x
at org.apache.hadoop.hdfs.server.namenode.DefaultAuthorizationProvider.checkFsPermission(DefaultAuthorizationProvider.java:281)
at org.apache.hadoop.hdfs.server.namenode.DefaultAuthorizationProvider.check(DefaultAuthorizationProvider.java:262)
at org.apache.hadoop.hdfs.server.namenode.DefaultAuthorizationProvider.check(DefaultAuthorizationProvider.java:242)
at org.apache.hadoop.hdfs.server.namenode.DefaultAuthorizationProvider.checkPermission(DefaultAuthorizationProvider.java:169)
at org.apache.sentry.hdfs.SentryAuthorizationProvider.checkPermission(SentryAuthorizationProvider.java:178)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkPermission(FSPermissionChecker.java:152)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:3560)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:3543)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkAncestorAccess(FSDirectory.java:3525)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkAncestorAccess(FSNamesystem.java:6592)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startFileInternal(FSNamesystem.java:2821)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startFileInt(FSNamesystem.java:2739)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startFile(FSNamesystem.java:2624)
at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.create(NameNodeRpcServer.java:599)
at org.apache.hadoop.hdfs.server.namenode.AuthorizationProviderProxyClientProtocol.create(AuthorizationProviderProxyClientProtocol.java:112)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.create(ClientNamenodeProtocolServerSideTranslatorPB.java:401)
at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:617)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1073)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2141)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2137)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1714)
at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2135)
这是我在core-site.xml中的配置
<property>
<name>hadoop.proxyuser.striim1.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.striim1.groups</name>
<value>*</value>
</property>
这是我试图访问的文件夹的权限设置
drwxr-xr-x - striim1 striim1 0 2017-05-19 02:50 /user/striim1
这个例外使我想到以下问题
1) 即使我将超级用户的ugi传递给代理用户joy。为什么客户机要在用户joy的上下文中创建文件?
2) 在我的集群部署中,“striim1”只是一个拥有kerberos凭据的用户,而不是这个定义中的超级用户。只有当“striim1”是超级用户或添加到超级用户组时,模拟才能工作吗?
3) 我试图模拟的用户的名称是否应该是有效的os用户?如果没有,会发生什么,在这方面做了什么验证?
4) 我试图使用这个模拟用户编写的目录的权限设置应该是什么?是属于超级用户组还是属于超级用户组?
5) 是否应在我的应用程序中显式调用ugi.createproxyuser?假设我从我想使用超级用户模拟的用户那里执行我的应用程序,然后我将代理用户配置(基本上是传递core site.xm)传递给我的应用程序?这就够了吗(我期望像createproxyuser这样的东西在内部被调用(通过将当前应用程序执行用户作为要模拟的用户)。
提前谢谢。
当做,
尼兰詹
1条答案
按热度按时间vatpfxk51#
1) 即使我将超级用户的ugi传递给代理用户joy。为什么客户机要在用户joy的上下文中创建文件?
当使用代理用户功能来调用hdfs服务(如namenode)时,您将作为“真实用户”进行身份验证,然后调用的执行就好像是由代理用户或“有效用户”完成的一样。在您的代码示例中,striim1是真正的用户,joy是有效的用户。这意味着此客户机代码使用striim1的kerberos凭据对namenode进行身份验证,然后它切换到充当joy真正调用的角色。就像joy正在创建文件一样,这对于文件权限检查非常重要。
你可能还想知道,即使你打电话来,为什么它也会起到快乐的作用
FileSystem#create
外面的doAs
. 那是因为FileSystem
示例永久绑定到特定UserGroupInformation
当它被创建时。因为您在doAs
以代理用户joy的身份运行时,该服务器上的后续操作FileSystem
继续快乐地执行。2) 在我的集群部署中,“striim1”只是一个拥有kerberos凭据的用户,而不是这个定义中的超级用户。只有当“striim1”是超级用户或添加到超级用户组时,模拟才能工作吗?
没有要求真正的用户必须是hdfs超级用户。使用striim1的设置似乎运行良好,因为它作为striim1(真实用户)进行身份验证,然后作为joy(有效用户)执行。
3) 我试图模拟的用户的名称是否应该是有效的os用户?如果没有,会发生什么,在这方面做了什么验证?
对于用户来说,服务器上的操作系统级别并不是一个严格的要求。这样做的结果是,当namenode执行调用时,它将像用户不是任何组的成员一样执行(组成员身份是通过操作系统集成来确定的,例如本地定义的组或pamëldap。)如果用户不需要具有组成员身份来访问某些文件,那么这不会是一个问题。
4) 我试图使用这个模拟用户编写的目录的权限设置应该是什么?是属于超级用户组还是属于超级用户组?
在您的示例中,调用的执行就像用户是joy一样。您可以自由选择满足您授予或拒绝访问joy的要求的任何文件权限设置。要在目录中创建新文件,用户必须对路径祖先的所有子组件具有执行权限(示例中为/user和/user/striim1),并对直接祖先具有写入权限(示例中为/user/striim1)。
有关此主题的详细讨论,请参阅《hdfs权限指南》。
5) 是否应在我的应用程序中显式调用ugi.createproxyuser?假设我从我想使用超级用户模拟的用户那里执行我的应用程序,然后我将代理用户配置(基本上是传递core site.xm)传递给我的应用程序?这就够了吗(我期望像createproxyuser这样的东西在内部被调用(通过将当前应用程序执行用户作为要模拟的用户)。
听起来您正在寻找一种解决方案,不需要专门为代理用户处理编写应用程序代码,而是可以在执行程序时从外部控制代理用户的使用。如果是这样,那么可以通过设置
HADOOP_PROXY_USER
要模拟的用户的环境变量。例如,你可以跑步kinit -kt
以striim1身份登录,然后set HADOOP_PROXY_USER=joy
然后执行你的程序。有关此功能实现的讨论,请参见hadoop-8561。这是文章的重点
UserGroupInformation
实现此功能的代码:https://github.com/apache/hadoop/blob/release-2.7.0/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/usergroupinformation.java#l803