vlambda博客
学习文章列表

聊聊HDFS中的权限管理

HDFS是一个面向多用户的分布式文件系统。既然是多用户,那么不同用户存储的文件通常需要进行权限隔离,防止被其他用户修改或误删。本文就来聊聊HDFS中的权限管理。


权限校验


要启用权限校验,首先需要在NN中配置开启。


配置项dfs.permissions.enabled控制权限的开关,true表示开启,false表示关闭。

没有开启权限控制时,任何用户都可以对任意文件进行读写删除等操作。


<property>  <name>dfs.permissions.enabled</name>  <value>true</value></property>


HDFS中的权限方式和linux文件系统中的权限模型是一样的,均采用UGO模型。

U表示User,G表示Group,O表示Other。每个文件的权限都基于UGO来设置。


而权限又包括可读(r),可写(w),可执行(x),三个为一组,对应UGO分别进行设置。


我们来实际验证下:使用hncscwc用户创建/hncscwc目录,并上传文件到该目录中,然后使用root用户删除该文件。


未开启权限校验之前,root用户可以成功删除文件。


开启权限校验之后,root用户无法删除该文件,并提示没有权限。

聊聊HDFS中的权限管理


那么如果想要让root用户可以删除hncscwc上传的文件,有什么办法呢?一种简单粗暴的方式是通过chmod改变文件的权限。例如上面将目录和文件的权限都设置为777后,root用户就可以成功删除文件了。


但显然这种方式是不友好的,因为几乎和没有开启权限校验一样。因此HDFS同样也是实现了类似linux文件系统中ACL。


ACL


和权限校验一样,ACL的开启有对应的配置项,true表示开启,false表示关闭

<property> <name>dfs.namenode.acls.enabled</name>    <value>true</value></property>


开启ACL之后,可以通过命令设置和获取文件/目录的ACL。

# 获取指定文件/目录的ACLhdfs dfs -getfacl [-R] <path>-R: 递归列出所有w文件和目录的ACL
# 设置指定文件/目录的ACLhdfs dfs -setfacl [-R] [-b|-k -m|-x <acl_spec> <path>] [--set <acl_spec <path>]-b:    删除基本ACL条目之外的所有条目。保留用户、组和其他的条目-k:    移除默认的ACL-R:    递归操作所有文件和目录-m:    修改ACL,将新条目添加到ACL,并保留现有条目-x: 删除指定的ACL--set:    完全t替换ACL,acl_spec必须包含用户,组和其他权限信息acl_spec:  用逗号分隔的ACL列表path: 需要设置ACL的文件l路径


这里不展开说明命令的细节,详细参考官方文档。


还是按照上面的场景,对/hncscwc/info设置ACL允许root用户写入。


聊聊HDFS中的权限管理


从上图可以看到,文件设置ACL之后,权限后面会多出一个“+”,表示该文件有设置ACL。


通过命令查看该文件的ACL信息:


聊聊HDFS中的权限管理


接着使用root用户追加写入该文件,此时root用户可以成功追加写入,而使用其他用户追加写入时,写入失败并提示没有权限。



由此可见,ACL生效了,也确实达到了我们想要的效果。


超级用户


在HDFS中,有一个超级用户的概念,该用户可以成功执行任意动作而不需要进行权限校验。


超级用户没有固定的值,而是启动NN的用户就是超级用户。


此外,还可以通过配置来指明一个组为超级用户组,在该组中的所有用户均为超级用户,具体配置为:

<property> <name>dfs.permissions.superusergroup</name>    <value>supergroup</value></property>


内部实现

在NN内部,权限校验主要有两个类,部分关键代码如下所示:

public abstract class INodeAttributeProvider{    //访问控制执行者接口    public interface AccessControlEnforcer {        // 省略了参数列表     public abstract void checkPermission(...)    }        public abstract void start();        public abstract void stop();        public AccessControlEnforcer getExternalAccessControlEnforcer(AccessControlEnforcer defaultEnforcer) {     return defaultEnforcer;    }}

该类为抽象类,用于HDFS委派授权,该类中定义了一个接口AccessControlEnforcer,并定义方法checkPermission,该方法需要实现类重写,以实现最终的权限校验逻辑。


class FSPermissionChecker implements AccessControlEnforcer { private AccessControlEnforcer getAccessControlEnforcer() {        // 这里的attributeProvider就是上面抽象类的具体实现类        // 如果attributeProvider 则使用自身 return (attributeProvider != null) ? attributeProvider.getExternalAccessControlEnforcer(this) : this; }     // 外部调用接口, 省略了参数列表    void checkPermission(...) {     AccessControlEnforcer enforcer = getAccessControlEnforcer();     enforcer.checkPermission(...)    }        // 实现AccessControlEnforcer接口的方法实现    public void checkPermission(...) {    }}


简单总结下鉴权流程,如下图所示:


从流程可以看出,通过编写INodeAttributeProvider继承类,和接口AccessControlEnforcer实现,HDFS可以支持外部以插件的方式实现定制的权限控制。而实际上,开源的大数据权限管理项目Ranger,sentry就是利用了这一点,以插件的方式扩展实现了权限校验。


好了,本文就介绍到这里了,原创不易,点赞,在看,分享是最好的支持, 谢谢~